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() {@Overridepublic 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 1sub thread seq of 1, loop of 1sub thread seq of 2, loop of 1sub thread seq of 3, loop of 1sub thread seq of 4, loop of 1sub thread seq of 5, loop of 1sub thread seq of 6, loop of 1sub thread seq of 7, loop of 1sub thread seq of 8, loop of 1sub thread seq of 9, loop of 1main thread seq of 0, loop of 1main thread seq of 1, loop of 1main thread seq of 2, loop of 1main thread seq of 3, loop of 1main thread seq of 4, loop of 1main thread seq of 5, loop of 1main thread seq of 6, loop of 1main thread seq of 7, loop of 1main thread seq of 8, loop of 1main 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的队列
