Java实现多线程轮流打印数字的关键是精确控制执行顺序和状态同步,主流方式有三种:1. synchronized+wait/notify(适合初学);2. ReentrantLock+Condition(唤醒精准、语义清晰);3. AtomicInteger自旋(轻量但CPU占用高)。

Java 中实现多线程轮流打印数字(比如线程 A 打印 1、4、7…,线程 B 打印 2、5、8…,线程 C 打印 3、6、9…),关键在于**精确控制线程执行顺序和状态同步**,避免竞态、丢失唤醒或死锁。常用且可靠的方式是结合 共享状态变量 + wait/notify 或 Lock + Condition,下面给出两种主流、易理解的实现思路。
用 synchronized + wait/notify 控制轮转
适合初学理解线程协作本质。核心是:一个共享计数器(如 current)和一个标识当前该谁打印的变量(如 turn),每个线程只在轮到自己时才执行并唤醒下一个。
- 定义共享对象(如
Object lock = new Object())作为同步监视器 - 用
int current = 1记录待打印数字,int turn = 0表示第 0 个线程(A)先开始(假设线程按 0/1/2 编号) - 每个线程循环中:先 synchronized 持有锁 → 检查是否轮到自己(
turn == myIndex)→ 是则打印、更新current和turn(取模下一轮),再notifyAll();否则wait() - 注意:必须用
while而非if判断条件(防止虚假唤醒)
用 ReentrantLock + Condition 实现更清晰的等待队列
比 wait/notify 更灵活,可为每个线程分配独立的 Condition,避免“惊群效应”(notifyAll 唤醒所有但只一个能干活)。
- 创建
ReentrantLock lock = new ReentrantLock() - 为每个线程声明专属
Condition:如Condition c0 = lock.newCondition()(对应线程 A) - 共享变量仍为
current和turn,逻辑类似:获取锁 → while 检查turn != myIndex则cMy.wait()→ 打印 → 更新 →cNext.signal()→ 释放锁 - 优势:唤醒精准,代码语义更明确,适合线程数固定且角色分明的场景
用 AtomicInteger + 自旋(轻量级,慎用于高竞争)
不依赖锁和等待,靠原子操作+忙等实现,适用于打印次数少、线程数少、对延迟敏感的简单场景。
立即学习“Java免费学习笔记(深入)”;
- 用
AtomicInteger state = new AtomicInteger(0)表示当前应由哪个线程执行(0→A,1→B,2→C) - 每个线程循环中:
while (state.get() != myIndex) Thread.yield()→ 打印 →state.set((myIndex + 1) % N) - 缺点:CPU 占用高,无法控制总打印次数,不适合长时间运行或线程数多的情况
补充要点:如何终止与边界控制
实际使用需考虑停止条件,例如只打印到 30:
- 引入
volatile boolean finished = false或共享AtomicBoolean - 每次打印前检查
if (current > MAX) { finished = true; break; } - 在唤醒逻辑后加
if (finished) notifyAll() / signalAll(),确保阻塞线程能及时退出 - 主线程启动所有工作线程后,可用
thread.join()等待全部结束
不复杂但容易忽略细节。选哪种方式取决于你对可读性、性能、健壮性的侧重——教学推荐 synchronized + wait/notify;生产建议 Lock + Condition;追求极简且场景受限可试 AtomicInteger 自旋。



















