面试真题(多线程交替打印ABC,中间变化打印顺序)

1.题目 线程1只打印t1,线程2只打印t2,线程3只打印t3,控制他输出t1,t2,t3这样5遍,然后t2,t3,t1打印,最后t3,t1,t2之后一直循环。
2.思路 有关多线程的知识不明白的可以参考:https://blog.csdn.net/qq_35688140/article/category/9322916
第一步: 【面试真题(多线程交替打印ABC,中间变化打印顺序)】这个题第一眼有点类似于常见题“两个线程循环打印AB”,然后可以利用lock。newCondition().
(1)最开始标志位flag为0,此时线程2进入循环condition2.await(),线程3进入循环condition3.await(),线程1进入发现标志位flag满足不用await的条件,向下走,打印"t1",并将标志位设置成了1.
(2)同(1),执行完成线程2,打印了"t2",标志位设置成2,
(3)同(1),执行完成线程3,打印了"t3",标志位设置成0
这样就完成了循环打印"ABC".
第二步: 利用CyclicBarrier 的特性,它可以同步进程,在遇到CyclicBarrier.await()之前一直等待所有的线程结束,才会运行CyclicBarrier.await()后面的代码。利用这一特性,我们在CyclicBarrier.await()结束时,在回调函数中,修改下次循环打印的初始flag即可。
ps:此处之所以不适用CountDownLatch是因为CountDownLatch是一次性的,而CyclicBarrier.await()可以循环使用。
3.代码

package com.qianliu.concurrency; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class test {public static void main(String[] args) { Print print = new Print(); Thread t1 = new Thread(new Runnable() { @Override public void run() { while (true){ print.print1Cycle(); }} }); Thread t2 = new Thread(new Runnable() { @Override public void run() { while (true){ print.print2Cycle(); }} }); Thread t3 = new Thread(new Runnable() { @Override public void run() { while (true){ print.print3Cycle(); } } }); t1.start(); t2.start(); t3.start(); }}class Print{ //控制打印第一次的打印值 static volatile int flag=0; static CyclicBarrier cyclicBarrier1 = new CyclicBarrier(3,()->{ System.out.println("==============第一轮15次打印============="); //下一次重t2开始执行 flag = 1; }); static CyclicBarrier cyclicBarrier2 = new CyclicBarrier(3,()->{ // 第三轮在t3线程处开始 flag = 2; System.out.println("==============第二轮15次打印============="); }); static CyclicBarrier cyclicBarrier3 = new CyclicBarrier(3,()->{ System.out.println("==============第三轮15次打印============="); //下一次(15次打印)从t1开始 flag =0; }); Lock lock = new ReentrantLock(); Condition condition1 = lock.newCondition(); Condition condition2 = lock.newCondition(); Condition condition3 = lock.newCondition(); //增加回环栅栏3 public void addCyclicBarrier3(){ try { cyclicBarrier3.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }//增加回环栅栏2 public void addCyclicBarrier2(){ try { cyclicBarrier2.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }//增加回环栅栏1 public void addCyclicBarrier1(){ try { cyclicBarrier1.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }//循环打印5次t1 public void print1(){ for(int i=0; i<5; i++) { lock.lock(); try { //循环检测标志,不是0,不发出打印A信号 while(flag !=0) condition1.await(); System.out.println("t1"); flag=1; //发出打印b的信号 condition2.signal(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } }//循环打印5次t2 public void print2(){ for(int i=0; i<5; i++) { lock.lock(); try { //循环检测标志,不是0,不发出打印A信号 while(flag !=1) condition2.await(); System.out.println("t2"); flag=2; //发出打印b的信号 condition3.signal(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } }//循环打印5次t3 public void print3(){ for(int i=0; i<5; i++) { lock.lock(); try { //循环检测标志,不是0,不发出打印A信号 while(flag !=2) condition3.await(); System.out.println("t3"); flag=0; //发出打印b的信号 condition1.signal(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } }public void print1Cycle() { print1(); // 回环栅栏 addCyclicBarrier1(); print1(); addCyclicBarrier2(); print1(); addCyclicBarrier3(); }public void print2Cycle(){print2(); //回环栅栏 addCyclicBarrier1(); print2(); //回环栅栏 addCyclicBarrier2(); print2(); addCyclicBarrier3(); }public void print3Cycle() { print3(); //回环栅栏 addCyclicBarrier1(); print3(); //回环栅栏 addCyclicBarrier2(); print3(); addCyclicBarrier3(); } }

结果演示:
面试真题(多线程交替打印ABC,中间变化打印顺序)
文章图片

面试真题(多线程交替打印ABC,中间变化打印顺序)
文章图片

面试真题(多线程交替打印ABC,中间变化打印顺序)
文章图片

    推荐阅读