通过一道面试题了解Condition线程通信
Condition
- Condition接口描述了可能会与锁有关联的条件变量。这些变量在用法与使用Object.wait访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个Lock可能与多个Condition对象关联。为了避免兼容性问题,Condition方法的名称与对应的Object版本中的不同;
- 在Condition对象中,与wait、notify和notifyAll方法对应的分别是await、signal和signalAll;
- Condition实例实质上被绑定到一个锁上。要为特定Lock实例获得Condition实例,请使用器newCondition()方法。
面试题
1 package com.ccfdod.juc; 2 3 import java.util.concurrent.locks.Condition; 4 import java.util.concurrent.locks.Lock; 5 import java.util.concurrent.locks.ReentrantLock; 6 7 /** 8 * 题目:编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。 9 * 如:ABCABCABC…… 10 */ 11 class AlternateDemo { 12 //标志当前由哪一个线程输出,1代表A,2代表B,3代表C 13 private int number = 1; 14 15 Lock lock = new ReentrantLock(); 16 17 //Condition的强大之处在于它可以为多个线程间建立不同的Condition 18 Condition condition1 = lock.newCondition(); 19 Condition condition2 = lock.newCondition(); 20 Condition condition3 = lock.newCondition(); 21 22 // loopNum:当前循环轮数 23 public void loopA(int loopNum) { 24 //上锁 25 lock.lock(); 26 try { 27 while (number != 1) { 28 //等待 29 condition1.await(); 30 } 31 32 System.out.println(Thread.currentThread().getName() + ", currentLoopNum is " + loopNum); 33 number = 2; 34 //唤醒 35 condition2.signal(); 36 37 } catch (InterruptedException e) { 38 e.printStackTrace(); 39 } finally { 40 //确保释放锁 41 lock.unlock(); 42 } 43 } 44 45 public void loopB(int loopNum) { 46 lock.lock(); 47 try { 48 while (number != 2) { 49 condition2.await(); 50 } 51 52 System.out.println(Thread.currentThread().getName() + ", currentLoopNum is " + loopNum); 53 number = 3; 54 condition3.signal(); 55 56 } catch (InterruptedException e) { 57 e.printStackTrace(); 58 } finally { 59 lock.unlock(); 60 } 61 } 62 63 public void loopC(int loopNum) { 64 lock.lock(); 65 try { 66 while (number != 3) { 67 condition3.await(); 68 } 69 70 System.out.println(Thread.currentThread().getName() + ", currentLoopNum is " + loopNum); 71 number = 1; 72 condition1.signal(); 73 74 } catch (InterruptedException e) { 75 e.printStackTrace(); 76 } finally { 77 lock.unlock(); 78 } 79 } 80 } 81 82 public class TestABCAlternate { 83 84 public static void main(String[] args) { 85 AlternateDemo ad = new AlternateDemo(); 86 87 new Thread(new Runnable() { 88 89 @Override 90 public void run() { 91 for (int i = 0; i < 10; i++) 92 ad.loopA(i); 93 } 94 }, "A").start(); 95 96 new Thread(new Runnable() { 97 98 @Override 99 public void run() { 100 for (int i = 0; i < 10; i++) 101 ad.loopB(i); 102 } 103 }, "B").start(); 104 105 new Thread(new Runnable() { 106 107 @Override 108 public void run() { 109 for (int i = 0; i < 10; i++) 110 ad.loopC(i); 111 } 112 }, "C").start(); 113 } 114 }