condition是什么

条件(也称为条件队列或条件变量)为一个线程提供了一种暂停执行(“等待”)的方法,直到另一个线程通知某个状态条件现在可能为真。
Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法。
不同的是,Object中的wait(),notify(),notifyAll()方法是和”同步锁“(synchronized关键字)捆绑使用的;而Condition是需要与”互斥锁“/“共享锁“(Lock)捆绑使用的。

Condition函数列表

  1. // 造成当前线程在接到信号或被中断之前一直处于等待状态。
  2. void await()
  3. // 造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
  4. boolean await(long time, TimeUnit unit)
  5. // 造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
  6. long awaitNanos(long nanosTimeout)
  7. // 造成当前线程在接到信号之前一直处于等待状态。
  8. void awaitUninterruptibly()
  9. // 造成当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。
  10. boolean awaitUntil(Date deadline)
  11. // 唤醒一个等待线程。
  12. void signal()
  13. // 唤醒所有等待线程。
  14. void signalAll()

实例

  1. public class ConditionTest {
  2. public static void main(String[] args) {
  3. final Business business = new Business();
  4. final BusinessSynchronized businessSynchronized = new BusinessSynchronized();
  5. new Thread(new Runnable() {
  6. @Override
  7. public void run() {
  8. //threadExecute(business, "sub");
  9. threadExecuteSynchronized(businessSynchronized, "sub");
  10. }
  11. }).start();
  12. //threadExecute(business, "main");
  13. threadExecuteSynchronized(businessSynchronized, "main");
  14. }
  15. public static void threadExecute(Business business, String threadType) {
  16. for (int i = 0; i < 2; i++) {
  17. try {
  18. if ("main".equals(threadType)) {
  19. business.main(i);
  20. } else {
  21. business.sub(i);
  22. }
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. }
  28. public static void threadExecuteSynchronized(BusinessSynchronized business, String threadType) {
  29. for (int i = 0; i < 2; i++) {
  30. try {
  31. if ("main".equals(threadType)) {
  32. business.main(i);
  33. } else {
  34. business.sub(i);
  35. }
  36. } catch (InterruptedException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. }
  41. }
  42. class Business {
  43. private boolean bool = true;
  44. private Lock lock = new ReentrantLock();
  45. private Condition condition = lock.newCondition();
  46. public /*synchronized*/ void main(int loop) throws InterruptedException {
  47. lock.lock();
  48. try {
  49. while (bool) {
  50. condition.await();//this.wait();
  51. }
  52. for (int i = 0; i < 10; i++) {
  53. System.out.println("main thread seq of " + i + ", loop of " + loop);
  54. }
  55. bool = true;
  56. condition.signal();//this.notify();
  57. } finally {
  58. lock.unlock();
  59. }
  60. }
  61. public /*synchronized*/ void sub(int loop) throws InterruptedException {
  62. lock.lock();
  63. try {
  64. while (!bool) {
  65. condition.await();//this.wait();
  66. }
  67. for (int i = 0; i < 10; i++) {
  68. System.out.println("sub thread seq of " + i + ", loop of " + loop);
  69. }
  70. bool = false;
  71. condition.signal();//this.notify();
  72. } finally {
  73. lock.unlock();
  74. }
  75. }
  76. }
  77. class BusinessSynchronized {
  78. private boolean bool = true;
  79. //private Lock lock = new ReentrantLock();
  80. //private Condition condition = lock.newCondition();
  81. public synchronized void main(int loop) throws InterruptedException {
  82. //lock.lock();
  83. //try {
  84. while (bool) {
  85. this.wait();
  86. }
  87. for (int i = 0; i < 10; i++) {
  88. System.out.println("main thread seq of " + i + ", loop of " + loop);
  89. }
  90. bool = true;
  91. this.notify();
  92. //} finally {
  93. // lock.unlock();
  94. //}
  95. }
  96. public synchronized void sub(int loop) throws InterruptedException {
  97. //lock.lock();
  98. //try {
  99. while (!bool) {
  100. this.wait();
  101. }
  102. for (int i = 0; i < 10; i++) {
  103. System.out.println("sub thread seq of " + i + ", loop of " + loop);
  104. }
  105. bool = false;
  106. this.notify();
  107. //} finally {
  108. // lock.unlock();
  109. //}
  110. }
  111. }

Condition和synchronized是一样的结果

  1. sub thread seq of 0, loop of 1
  2. sub thread seq of 1, loop of 1
  3. sub thread seq of 2, loop of 1
  4. sub thread seq of 3, loop of 1
  5. sub thread seq of 4, loop of 1
  6. sub thread seq of 5, loop of 1
  7. sub thread seq of 6, loop of 1
  8. sub thread seq of 7, loop of 1
  9. sub thread seq of 8, loop of 1
  10. sub thread seq of 9, loop of 1
  11. main thread seq of 0, loop of 1
  12. main thread seq of 1, loop of 1
  13. main thread seq of 2, loop of 1
  14. main thread seq of 3, loop of 1
  15. main thread seq of 4, loop of 1
  16. main thread seq of 5, loop of 1
  17. main thread seq of 6, loop of 1
  18. main thread seq of 7, loop of 1
  19. main thread seq of 8, loop of 1
  20. main thread seq of 9, loop of 1
  21. 进程已结束,退出代码0

Object监视器方法与Condition接口最大区别
Object监视器的等待队列个数只有一个,但是Condition等待队列可以为多个;
我们接下来把Condition的API代码拿出来看看:

  1. public class SynchronizedTest {
  2. public static void main(String[] args) {
  3. BoundedBuffer boundedBuffer = new BoundedBuffer();
  4. for (int i = 0; i < 5; i++) {
  5. int finalI = i;
  6. new Thread(() -> {
  7. try {
  8. boundedBuffer.put(finalI);
  9. } catch (InterruptedException e) {
  10. e.printStackTrace();
  11. }
  12. }
  13. ).start();
  14. }
  15. for (int i = 10; i < 15; i++) {
  16. int finalI = i;
  17. new Thread(() -> {
  18. try {
  19. boundedBuffer.put(finalI);
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. ).start();
  25. }
  26. try {
  27. for (int i = 0; i < 15; i++) {
  28. System.out.println(boundedBuffer.take());
  29. }
  30. } catch (InterruptedException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. }
  35. class BoundedBuffer {
  36. final Lock lock = new ReentrantLock();//锁对象
  37. final Condition notFull = lock.newCondition();//写线程条件
  38. final Condition notEmpty = lock.newCondition();//读线程条件
  39. final Object[] items = new Object[100];//缓存队列
  40. int putptr/*写索引*/, takeptr/*读索引*/, count/*队列中存在的数据个数*/;
  41. public void put(Object x) throws InterruptedException {
  42. lock.lock();
  43. try {
  44. while (count == items.length)//如果队列满了
  45. notFull.await();//阻塞写线程
  46. items[putptr] = x;//赋值
  47. if (++putptr == items.length) putptr = 0;//如果写索引写到队列的最后一个位置了,那么置为0
  48. ++count;//个数++
  49. notEmpty.signal();//唤醒读线程
  50. } finally {
  51. lock.unlock();
  52. }
  53. }
  54. public Object take() throws InterruptedException {
  55. lock.lock();
  56. try {
  57. while (count == 0)//如果队列为空
  58. notEmpty.await();//阻塞读线程
  59. Object x = items[takeptr];//取值
  60. if (++takeptr == items.length) takeptr = 0;//如果读索引读到队列的最后一个位置了,那么置为0
  61. --count;//个数--
  62. notFull.signal();//唤醒写线程
  63. return x;
  64. } finally {
  65. lock.unlock();
  66. }
  67. }
  68. }

我们执行一下:
image.png
可以看到这是一个等待队列,FIFO的队列