condition是什么
条件(也称为条件队列或条件变量)为一个线程提供了一种暂停执行(“等待”)的方法,直到另一个线程通知某个状态条件现在可能为真。
Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法。
不同的是,Object中的wait(),notify(),notifyAll()方法是和”同步锁“(synchronized关键字)捆绑使用的;而Condition是需要与”互斥锁“/“共享锁“(Lock)捆绑使用的。
Condition函数列表
// 造成当前线程在接到信号或被中断之前一直处于等待状态。
void await()
// 造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
boolean await(long time, TimeUnit unit)
// 造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
long awaitNanos(long nanosTimeout)
// 造成当前线程在接到信号之前一直处于等待状态。
void awaitUninterruptibly()
// 造成当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。
boolean awaitUntil(Date deadline)
// 唤醒一个等待线程。
void signal()
// 唤醒所有等待线程。
void signalAll()
实例
public class ConditionTest {
public static void main(String[] args) {
final Business business = new Business();
final BusinessSynchronized businessSynchronized = new BusinessSynchronized();
new Thread(new Runnable() {
@Override
public void run() {
//threadExecute(business, "sub");
threadExecuteSynchronized(businessSynchronized, "sub");
}
}).start();
//threadExecute(business, "main");
threadExecuteSynchronized(businessSynchronized, "main");
}
public static void threadExecute(Business business, String threadType) {
for (int i = 0; i < 2; i++) {
try {
if ("main".equals(threadType)) {
business.main(i);
} else {
business.sub(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void threadExecuteSynchronized(BusinessSynchronized business, String threadType) {
for (int i = 0; i < 2; i++) {
try {
if ("main".equals(threadType)) {
business.main(i);
} else {
business.sub(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Business {
private boolean bool = true;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public /*synchronized*/ void main(int loop) throws InterruptedException {
lock.lock();
try {
while (bool) {
condition.await();//this.wait();
}
for (int i = 0; i < 10; i++) {
System.out.println("main thread seq of " + i + ", loop of " + loop);
}
bool = true;
condition.signal();//this.notify();
} finally {
lock.unlock();
}
}
public /*synchronized*/ void sub(int loop) throws InterruptedException {
lock.lock();
try {
while (!bool) {
condition.await();//this.wait();
}
for (int i = 0; i < 10; i++) {
System.out.println("sub thread seq of " + i + ", loop of " + loop);
}
bool = false;
condition.signal();//this.notify();
} finally {
lock.unlock();
}
}
}
class BusinessSynchronized {
private boolean bool = true;
//private Lock lock = new ReentrantLock();
//private Condition condition = lock.newCondition();
public synchronized void main(int loop) throws InterruptedException {
//lock.lock();
//try {
while (bool) {
this.wait();
}
for (int i = 0; i < 10; i++) {
System.out.println("main thread seq of " + i + ", loop of " + loop);
}
bool = true;
this.notify();
//} finally {
// lock.unlock();
//}
}
public synchronized void sub(int loop) throws InterruptedException {
//lock.lock();
//try {
while (!bool) {
this.wait();
}
for (int i = 0; i < 10; i++) {
System.out.println("sub thread seq of " + i + ", loop of " + loop);
}
bool = false;
this.notify();
//} finally {
// lock.unlock();
//}
}
}
Condition和synchronized是一样的结果
sub thread seq of 0, loop of 1
sub thread seq of 1, loop of 1
sub thread seq of 2, loop of 1
sub thread seq of 3, loop of 1
sub thread seq of 4, loop of 1
sub thread seq of 5, loop of 1
sub thread seq of 6, loop of 1
sub thread seq of 7, loop of 1
sub thread seq of 8, loop of 1
sub thread seq of 9, loop of 1
main thread seq of 0, loop of 1
main thread seq of 1, loop of 1
main thread seq of 2, loop of 1
main thread seq of 3, loop of 1
main thread seq of 4, loop of 1
main thread seq of 5, loop of 1
main thread seq of 6, loop of 1
main thread seq of 7, loop of 1
main thread seq of 8, loop of 1
main thread seq of 9, loop of 1
进程已结束,退出代码0
Object监视器方法与Condition接口最大区别
Object监视器的等待队列个数只有一个,但是Condition等待队列可以为多个;
我们接下来把Condition的API代码拿出来看看:
public class SynchronizedTest {
public static void main(String[] args) {
BoundedBuffer boundedBuffer = new BoundedBuffer();
for (int i = 0; i < 5; i++) {
int finalI = i;
new Thread(() -> {
try {
boundedBuffer.put(finalI);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
).start();
}
for (int i = 10; i < 15; i++) {
int finalI = i;
new Thread(() -> {
try {
boundedBuffer.put(finalI);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
).start();
}
try {
for (int i = 0; i < 15; i++) {
System.out.println(boundedBuffer.take());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class BoundedBuffer {
final Lock lock = new ReentrantLock();//锁对象
final Condition notFull = lock.newCondition();//写线程条件
final Condition notEmpty = lock.newCondition();//读线程条件
final Object[] items = new Object[100];//缓存队列
int putptr/*写索引*/, takeptr/*读索引*/, count/*队列中存在的数据个数*/;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)//如果队列满了
notFull.await();//阻塞写线程
items[putptr] = x;//赋值
if (++putptr == items.length) putptr = 0;//如果写索引写到队列的最后一个位置了,那么置为0
++count;//个数++
notEmpty.signal();//唤醒读线程
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)//如果队列为空
notEmpty.await();//阻塞读线程
Object x = items[takeptr];//取值
if (++takeptr == items.length) takeptr = 0;//如果读索引读到队列的最后一个位置了,那么置为0
--count;//个数--
notFull.signal();//唤醒写线程
return x;
} finally {
lock.unlock();
}
}
}
我们执行一下:
可以看到这是一个等待队列,FIFO的队列