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();
}
}
结果演示:
文章图片
文章图片
文章图片
推荐阅读
- 主题(java服务,cpu高,内存高,telnet不通排查及分析)
- 并发|11.防刷限流
- 面试|【面试】--三个线程轮流打印ABC
- 并发|基于rxjava的生产消费模型
- LINUX|Linux网路编程基础及并发服务器
- 并发执行(串行)