Skip to content

面试速答(先看这里)

**一句话结论:**这也是一个典型的多线程之间通信的问题, 需要控制多个线程的执行顺序,即: a ➔ (b、c、d并发完成) ➔ e

60秒标准回答:

这也是一个典型的多线程之间通信的问题, 需要控制多个线程的执行顺序,即: a ➔ (b、c、d并发完成) ➔ e

这个场景中,用 CountDownLatch 就比较合适,大致流程如下

**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点

回答主线:

  • **要点1:**这个场景中,用 CountDownLatch 就比较合适,大致流程如下:

**记忆锚点:**bcd → latchBCDcountDown → latchAcountDown → CountDownLatch → latchBCDawait → latchAawait

加分表达:

  • 这也是一个典型的多线程之间通信的问题, 需要控制多个线程的执行顺序,即: a ➔ (b、c、d并发完成) ➔ e 这个场景中,用 CountDownLatch 就比较合适,大致流程如下: a 线程执行,执行完后 latchA.countDown() b/c/d 线程在 latchA.await() 处等待,直到a执行完一起开始 b/c/d 各自执行,完成后各…

追问准备:

  • 围绕「bcd」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「latchBCDcountDown」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「latchAcountDown」:底层原理是什么?使用时有哪些边界和常见坑?
  • 如果线上出现异常,你会如何定位、验证并规避?

典型回答 ​

这也是一个典型的多线程之间通信的问题, 需要控制多个线程的执行顺序,即:a ➔ (b、c、d并发完成) ➔ e

这个场景中,用 CountDownLatch 就比较合适,大致流程如下:

  • a线程执行,执行完后 latchA.countDown()
  • b/c/d线程在 latchA.await() 处等待,直到a执行完一起开始
  • b/c/d各自执行,完成后各自 latchBCD.countDown()
  • e线程在 latchBCD.await() 处等,等bcd都完成后执行

具体代码如下:

plain
import java.util.concurrent.CountDownLatch;

public class ThreadOrderControl {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latchA = new CountDownLatch(1); // 控制bcd等待a完成
        CountDownLatch latchBCD = new CountDownLatch(3); // 控制e等待bcd完成

        Thread a = new Thread(() -> {
            System.out.println("A start");
            // do something...
            System.out.println("A done");
            latchA.countDown(); // 通知bcd可以开始了
        });

        Runnable bcdTask = (String name) -> {
            try {
                latchA.await(); // 等a完成
                System.out.println(name + " start");
                // do something...
                System.out.println(name + " done");
                latchBCD.countDown(); // bcd每个线程做完都countDown一次
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        Thread b = new Thread(() -> bcdTask.run("B"));
        Thread c = new Thread(() -> bcdTask.run("C"));
        Thread d = new Thread(() -> bcdTask.run("D"));

        Thread e = new Thread(() -> {
            try {
                latchBCD.await(); // 等bcd全部完成
                System.out.println("E start");
                // do something...
                System.out.println("E done");
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        });

        // 启动所有线程
        a.start();
        b.start();
        c.start();
        d.start();
        e.start();
    }
}