共计 1516 个字符,预计需要花费 4 分钟才能阅读完成。
问题:如何实现三个线程交替循环打印?
示例: 线程 1 打印 A,线程 2 打印 B,线程 3 打印 C,要求交替打印,并且能够循环打印。
输入后果相似:ABCABCABC
这道题的难度是五颗星,在面试中也会常常遇到,如果是第一次见到这道题,很难在短时间内想出正当的解决方案。
如果只要求交替打印一次的话,实现比较简单,能够用 Thread.join() 办法,一个线程期待另一个线程执行实现。
当初要求循环打印,就波及线程间通信,必须要用到锁,一把锁必定不够。例如线程 1 开释锁之后,线程 2 和线程 3 都可能获取到锁,是随机的,当初要求必须是线程 2 获取到锁,所以须要三把锁。
执行过程:
线程 1 获取 A 锁,打印 A,开释 B 锁;
线程 2 获取 B 锁,打印 B,开释 C 锁;
线程 3 获取 C 锁,打印 C,开释 A 锁;
循环执行;
能够用 Synchronized 或者 ReentrantLock 实现,不过它们不能控制线程启动后的执行程序。因为三个线程启动后,都期待 CPU 调度执行,而 CPU 调度的程序又是随机的,所以不能保障线程 1 先执行。
有个能够控制线程启动后执行程序,又简略的实现形式,就是用 Semaphore(信号量),它能够管制共享资源的拜访个数。
应用形式:
-
初始化的时候,指定共享资源的个数
// 初始化一个资源 Semaphore semaphore = new Semaphore(1);
- 获取资源,获取资源后,semaphore 资源个数减 1,变成 0,其余线程再获取资源的时候就会阻塞期待
semaphore.acquire();
- 开释资源,semaphore 资源个数加 1,其余阻塞的线程就能够获取到资源了
semaphore.release();
代码实现:
/**
* @author yideng
* @apiNote 三个线程循环打印
*/
public class CirclePrint {
static class ThreadDemo extends Thread {
private Semaphore current;
private Semaphore next;
private String name;
/**
* 构造方法
* @param current 要获取的以后锁
* @param next 要开释的下一把锁
* @param name 打印内容
*/
public ThreadDemo(Semaphore current, Semaphore next, String name) {
this.current = current;
this.next = next;
this.name = name;
}
@Override
public void run() {for (int i = 0; i < 5; i++) {
try {
// 获取以后锁,而后打印
current.acquire();
System.out.print(name);
} catch (InterruptedException e) {e.printStackTrace();
}
// 开释下一把锁
next.release();}
}
}
public static void main(String[] args) {
// 初始化三把锁,只有 A 锁是可用的
Semaphore A = new Semaphore(1);
Semaphore B = new Semaphore(0);
Semaphore C = new Semaphore(0);
// 创立并启动三个线程,线程 1 获取 A 锁,开释 B 锁
new ThreadDemo(A, B, "A").start();
// 线程 2 获取 B 锁,开释 C 锁
new ThreadDemo(B, C, "B").start();
// 线程 3 获取 C 锁,开释 A 锁
new ThreadDemo(C, A, "C").start();}
}
输入后果:
ABCABCABCABCABC
你感觉怎么样?有更简略的解决方案吗?
正文完