当前位置: 首页 > news >正文

从一道面试题开始:如何让同时启动的线程按顺序执行?

最近准备面试刷题,遇到一个多线程问题:如何让 A、B、C 三个线程同时启动,却要按顺序先后执行(A -> B -> C)。

直觉上,“同时启动”意味着线程调度权交给操作系统,执行顺序理应不确定。那如何控制顺序?若让后一个线程等待前一个执行完毕,似乎又违背了“同时启动”的要求。

最初尝试 Thread.join():让 B 等待 A 执行完,C 等待 B 执行完,再按顺序启动它们。但很快发现问题——如果 B 和 C 的初始化逻辑依赖 A 对象,它们甚至无法在 A 启动前被创建。这本质上只是“顺序启动”,而非题目要求的“同时启动但顺序执行”。

理解关键点:

  • start() 仅通知系统线程就绪,run() 方法内的逻辑何时执行取决于 CPU 调度。
  • “启动”是状态,“执行”是动作,“等待”是一种阻塞状态。
  • 核心在于控制 run() 方法中关键逻辑的执行顺序,而非启动顺序本身。

使用 CountDownLatch 实现: CountDownLatch 是一个类似发令枪的同步工具。其核心是一个计数器:初始化设定计数值,线程调用 await() 阻塞等待;其他线程完成任务后调用 countDown() 减 1;当计数器归零,所有等待线程被唤醒继续执行。

利用两个 CountDownLatch:一个控制 B 等待 A 完成,一个控制 C 等待 B 完成。

public class ThreadOrder {public static void main(String[] args) {// 控制B等待A的信号CountDownLatch latchBwaitsA = new CountDownLatch(1);// 控制C等待B的信号CountDownLatch latchCwaitsB = new CountDownLatch(1);Thread a = new Thread(() -> {System.out.println("A starts");latchBwaitsA.countDown(); // A执行完毕,释放B线程的阻塞});Thread b = new Thread(() -> {try {latchBwaitsA.await(); // B等待A完成信号System.out.println("B starts");latchCwaitsB.countDown(); // B执行完毕,释放C线程的阻塞} catch (InterruptedException e) {Thread.currentThread().interrupt();}});Thread c = new Thread(() -> {try {latchCwaitsB.await(); // C等待B完成信号System.out.println("C starts");} catch (InterruptedException e) {Thread.currentThread().interrupt();}});// 真正的“同时启动”a.start();b.start();c.start();}
}

输出结果:

A starts
B starts
C starts

最关键的是,三个线程的 start() 方法几乎在同一时刻被调用,满足了“同时启动”的要求;而 run() 方法中关键逻辑的执行顺序(打印语句)则通过 CountDownLatch 实现了严格的 A -> B -> C 顺序,没有破坏“同时启动”的前提。

http://www.xdnf.cn/news/1438741.html

相关文章:

  • Bug排查日记:从发现到解决的完整记录
  • 在word中使用lateX公式的方法
  • 力扣115:不同的子序列
  • Unity Android 文件的读写
  • Delphi 5 中操作 Word 表格时禁用鼠标交互
  • 更新远程分支 git fetch
  • 揭开PCB隐形杀手:超周期报废的技术真相
  • AI编码生产力翻倍:你必须掌握的沟通、流程、工具与安全心法
  • 一键掌握服务器健康状态与安全风险
  • 同步工具的底层依赖:AQS
  • Kubernetes 中为 ZenTao 的 Apache 服务器添加请求体大小限制
  • 如何开发一款高稳定、低延迟、功能全面的RTSP播放器?
  • 时序数据库选型指南:为何Apache IoTDB成为工业物联网首选
  • JVM分析(OOM、死锁、死循环)(JProfiler、arthas、jvm自带工具)
  • STM32 - Embedded IDE - GCC - 使用 GCC 链接脚本限制 Flash 区域
  • 【Android】从复用到重绘的控件定制化方式
  • HarmonyOS 应用开发深度解析:基于 ArkTS 的声明式 UI 与状态管理艺术
  • HarmonyOS安装以及遇到的问题
  • Jenkins-Ansible部署discuz论坛
  • 38.Ansible判断+实例
  • PINN物理信息神经网络用于求解二阶常微分方程(ODE)的边值问题,Matlab实现
  • 力扣hot100:缺失的第一个正数(哈希思想)(41)
  • Qwen3-30B-A3B 模型解析
  • 【C++】迭代器详解与失效机制
  • # Shell 文本处理三剑客:awk、sed 与常用小工具详解
  • 【前端面试题✨】Vue篇(一)
  • Linux网络序列化与反序列化(6)
  • Linux文本处理——awk
  • 飞牛OS Nas,SSH安装宝塔后,smb文件不能共享问题
  • STM32——串口