Java多线程(ABC循环输出)
最近看到个Java多线程的面试题,要求3个线程,分别负责打印A/B/C,要求三个线程按照ABC的顺序输出N次
。
【Java多线程(ABC循环输出)】然后下面是我的解题思路:
首先,多线程问题,无脑起一个ThreadPoolExecutor
ThreadPoolExecutor executor = new ThreadPoolExecutor(poolSize,maxPoolSize,1,TimeUnit.MINUTES, new LinkedBlockingQueue<>(),new MyThreadFactory());
然后由于是要输出N次,在多线程问题中,我们需要一个支持CAS的
AtomicInteger
来计数AtomicInteger count = new AtomicInteger(1);
final int target = 10;
然后接下来就是关键了,ABC要顺序输出,也就是要实现以下流程:
- 一开始,不允许输出B/C
- 输出A后,可以输出B
- 输出B后,可以输出C
- 输出C后,
计数、判断
,并且可以输出A
- 一开始,线程B/C阻塞
- 线程A需要线程C释放后才能输出A,并且输出后释放线程B,然后阻塞
- 线程B需要线程A释放后才能输出B,并且输出后释放线程C,然后阻塞
- 线程C需要线程A释放后才能输出C,并且输出后释放线程A,然后阻塞
- 以此循环….然后在线程C进行计数、停止的判断
Semaphore
这个类,用资源量为1的信号量
来请求、释放资源,所以就要有了3个Semaphore
Semaphore A_B = new Semaphore(1);
Semaphore B_C = new Semaphore(1);
Semaphore C_A = new Semaphore(1);
然后就是开始运行三个线程前,对线程B/C的阻塞
A_B.acquire();
B_C.acquire();
最后就是输出部分了
executor.execute(() -> {
try {
while (true){
C_A.acquire();
System.out.print(count + ":");
System.out.print("A");
A_B.release();
}
} catch (InterruptedException ignored) {}
});
executor.execute(() -> {
try {
while (true){
A_B.acquire();
System.out.print("B");
B_C.release();
}
} catch (InterruptedException ignored) {
}
});
executor.execute(() -> {
try {
while (true){
B_C.acquire();
System.out.println("C");
if(count.getAndIncrement() >= target){
executor.shutdownNow();
}
C_A.release();
}
} catch (InterruptedException ignored) {
}
});
最终输出:
1:ABC完整代码:https://github.com/zhuyst/ThreadPoolExecutor_Learn/blob/master/src/indi/zhuyst/learn/abc/Main.java
2:ABC
3:ABC
4:ABC
5:ABC
6:ABC
7:ABC
8:ABC
9:ABC
10:ABC
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 爱就是希望你好好活着
- 昨夜小楼听风
- 知识
- 死结。
- 我从来不做坏事
- 烦恼和幸福
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- 事件代理