大家好,我是老三,这篇文章分享一道非常不错的题目:三个线程按序打印ABC。
很多读者朋友应该都觉得这道题目不难,这次给大家带来十二种做法,一定有你没有见过的新姿势。
1. synchronized+wait+notify
说到同步,我们很容易就想到synchronized。
线程间通信呢?我们先回忆一下线程间的调度。
编辑切换为居中
添加图片注释,不超过 140 字(可选)
多线程常见调度方法
可以看到,等待和运行之间的转换可以用wait和notify。
那么整体思路也就有了:
-
打印的时候需要获取锁
-
打印B的线程需要等待打印A线程执行完,打印C的线程需要等待打印B线程执行完
编辑切换为居中
添加图片注释,不超过 140 字(可选)
ABC-1
-
代码
public class ABC1 { //锁住的对象 private final static Object lock = new Object(); //A是否已经执行 private static boolean aExecuted = false; //B是否已经执行过 private static boolean bExecuted = false; public static void printA() { synchronized (lock) { System.out.println("A"); aExecuted = true; //唤醒所有等待线程 lock.notifyAll(); } } public static void printB() throws InterruptedException { synchronized (lock) { //获取到锁,但是要等A执行 while (!aExecuted) { lock.wait(); } System.out.println("B"); bExecuted = true; lock.notifyAll(); } } public static void printC() throws InterruptedException { synchronized (lock) { //获取到锁,但是要等B执行 while (!bExecuted) { lock.wait(); } System.out.println("C"); } } }
-
测试:后面几种方法的单测基本和这种方法一致,所以后面的单测就省略了。
@Test void abc1() { //线程A new Thread(() -> { ABC1.printA(); }, "A").start(); //线程B new Thread(() -> { try { ABC1.printB(); } catch (InterruptedException e) { e.printStackTrace(); } }, "B").start(); //线程C new Thread(() -> { try { ABC1.printC(); } catch (InterruptedException e) { e.printStackTrace(); } }, "C").start(); }
2. lock+全局变量state
还可以用lock+state来实现,大概思路:
-
用lock来实现同步
-
用全局变量state标识改哪个线程执行,不执行就释放锁
编辑切换为居中
添加图片注释,不超过 140 字(可选)
lock+state
-
代码
public class ABC2 { //可重入锁 private final static Lock lock = new ReentrantLock(); //判断是否执行:1表示应该A执行,2表示应该B执行,3表示应该C执行 private static int state = 1; public static void printA() { //自旋 while (state < 4) { try { //获取锁 lock.lock(); //并发情况下,不能用if,要用循环判断等待条件,避免虚假唤醒 while (state == 1) { System.out.println("A"); state++; } } finally { //要保证不执行的时候,锁能释放掉 lock.unlock(); } } } public static void printB() throws InterruptedException { while (state < 4) { try { lock.lock(); //获取到锁,应该执行 while (state == 2) { System.out.println("B"); state++; } } finally { lock.unlock(); } } } public static void printC() throws InterruptedException { while (state < 4) { try { lock.lock(); while (state == 3) { //获取到锁