java多线程交替打印本质是线程协作与状态控制,核心在于执行权判定、等待挂起与精准唤醒;synchronized+wait/notify依赖监视器和共享变量,reentrantlock+condition支持多等待队列实现定向唤醒,atomicinteger自旋则通过cas无锁轮询实现轻量协作。

Java 多线程交替打印(比如两个线程轮流输出 A、B,形成 ABAB…)本质是线程间协作与状态控制,核心在于“谁该执行、谁该等待、谁来唤醒”。不同锁机制实现的关键差异在于:如何安全地判断条件、如何挂起当前线程、如何精准唤醒目标线程。下面用三种主流方式分别说明,每种都给出可运行的最小完整示例和关键逻辑解释。
使用 synchronized + wait/notify
这是最经典、也是理解线程通信基础的方式。依赖对象监视器(monitor),通过 同一把锁 保证临界区互斥,用 wait() 阻塞当前线程并释放锁,用 notify()/notifyAll() 唤醒等待线程。
注意点:
- 必须在 synchronized 块内调用 wait/notify,否则抛 IllegalMonitorStateException
- wait 必须放在 while 循环中判断条件(防止虚假唤醒)
- notify 不保证唤醒特定线程,所以两个线程需共用一个锁对象,并靠共享变量(如 flag)决定谁该继续
示例逻辑(打印 10 次 AB):
共享变量 flag = true 表示轮到 A 打印;A 打印后设为 false 并 notify;B 等待 flag==false 时打印,再设回 true 并 notify。使用 ReentrantLock + Condition
比 synchronized 更灵活,支持多个等待队列。每个 Condition 对应一个“等待集”,可以做到精准唤醒指定类型的线程(比如只唤醒 B 线程,不惊动其他无关线程)。
关键操作:
- lock.lock() / lock.unlock() 替代 synchronized
- condition.await() 替代 wait(),会释放锁并进入对应等待队列
- condition.signal() 替代 notify(),只唤醒在该 condition 上 await 的线程
优势:避免 notify() 唤醒错误线程导致的额外等待;适合多角色协作场景(如 A/B/C 三线程交替)。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
使用 AtomicInteger + 自旋(无锁方式)
不依赖锁或阻塞,而是用原子变量(如 AtomicInteger)做状态标记,线程通过 CAS 自旋检查条件,满足才执行并更新状态。适用于竞争不激烈、执行体极轻量的场景。
特点:
- 没有上下文切换开销,但可能空转耗 CPU
- 需配合 Thread.yield() 或短时 TimeUnit.MILLISECONDS.sleep(1) 缓解忙等
- 代码简洁,但对初学者理解“协作”本质帮助较小
典型模式:用原子整数表示当前轮次(0→A,1→B),每个线程循环 compareAndSet 当前值并执行,成功后更新为下一个值。
选型建议
初学推荐 synchronized + wait/notify:概念清晰,JVM 层面保障强;
生产环境多线程协作复杂时选 ReentrantLock + Condition:可控性高、可读性好、调试友好;
高频低延迟且逻辑简单场景可试 AtomicInteger 自旋:但务必压测验证 CPU 占用和公平性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










