通过一道面试题了解Condition线程通信

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过一道面试题了解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 }

 

以上是关于通过一道面试题了解Condition线程通信的主要内容,如果未能解决你的问题,请参考以下文章

面试题2020-03-18线程间通信的方式

Java多线程与并发库4.传统线程同步通信技术

面试题:线程A打印1-10数字,打印到第5个数字时,通知线程B

一道非常棘手的 Java 面试题:i++ 是线程安全的吗?

提升--14---华为面试题: 交替输出,顺序打印

一道码分多址(CDMA)通信的计算题