java中实现多线程交替打印的核心是线程同步与协作,常用synchronized+wait/notify、reentrantlock+condition、atomicinteger自旋或semaphore四种方式,分别适用于不同场景。

Java 中实现多个线程按顺序交替打印字符,核心在于线程间的**同步与协作**,常用手段是结合 synchronized + wait()/notifyAll(),或使用 ReentrantLock + Condition,也可借助 AtomicInteger 或 Semaphore 控制执行权。关键不是“谁先抢到锁”,而是“谁该轮到自己打印”。
用 wait/notify 实现三线程交替打印 A/B/C
以三个线程分别打印 "A"、"B"、"C",循环 10 次(共 30 行)为例:
- 定义一个共享状态变量(如
int state = 0),表示当前该谁执行:0→A,1→B,2→C - 每个线程在
synchronized块中检查state是否轮到自己;不是就wait()暂停 - 轮到自己时打印,然后更新
state = (state + 1) % 3,再调用notifyAll()唤醒所有等待线程 - 注意:必须用
while判断条件(非if),防止虚假唤醒
用 ReentrantLock + Condition 精准唤醒指定线程
相比 notifyAll() 的广播式唤醒,Condition 可为每个线程分配专属等待队列,更高效:
- 创建一个
ReentrantLock和三个Condition(condA、condB、condC) - A 线程执行完后
condB.signal(),B 执行完condC.signal(),C 执行完condA.signal() - 每个线程启动时先
lock.lock(),再用while循环判断是否轮到自己,否则await() - 避免了不必要的唤醒和竞争,逻辑更清晰,适合角色固定、顺序严格的场景
用 AtomicInteger + 自旋(轻量级,适合简单场景)
若打印次数不多、对 CPU 效率不敏感,可用原子类配合忙等(busy-wait):
- 定义
AtomicInteger turn = new AtomicInteger(0) - 每个线程循环中不断读取
turn.get(),当值匹配自己序号时打印并incrementAndGet()(或用compareAndSet更新) - 为减少空转,可在每次不匹配时加
Thread.yield()或短暂停顿(如TimeUnit.NANOSECONDS.sleep(10)) - 优点是无锁、无阻塞;缺点是消耗 CPU,且不适用于高并发或实时性要求高的场景
用 Semaphore 控制通行权
信号量天然适合“发放许可证”的模型:
- 初始化三个
Semaphore:sA(1),sB(0),sC(0) —— 只有 A 最初有许可 - A 打印后,释放 sB(
sB.release());B 打印后释放 sC;C 打印后释放 sA - 每个线程先
acquire()自己的信号量,打印,再释放下一个线程的信号量 - 语义直观,不易出错,且支持超时控制(
tryAcquire(long, TimeUnit)),适合需要容错的场景
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











