Java两个线程怎么轮流执行?
- 后端开发
- 2025-06-08
- 3
在Java中实现两个线程轮流执行(交替运行)的核心在于线程间通信与同步,以下是几种专业、高效且符合生产环境标准的实现方案,每种方案附带完整代码示例和原理解析:
使用 synchronized + wait()/notify()(经典方案)
通过共享对象的监视器锁控制线程执行顺序:

原理:
- 共享锁 lock 作为同步监视器。
- 布尔标志 isThreadATurn 决定当前轮到哪个线程。
- wait() 释放锁并挂起线程,notifyAll() 唤醒等待线程。
- 严格交替:A执行 → 唤醒B → B执行 → 唤醒A → 循环。
使用 ReentrantLock + Condition(高性能方案)
利用显式锁的精准唤醒机制,避免无效竞争:

优势:
- 精确控制唤醒目标(signal() 替代 notifyAll()),减少无效线程竞争。
- 更高的并发性能(JDK推荐替代synchronized的方案)。
使用 Semaphore(信号量方案)
通过两个信号量控制执行权限:

import java.util.concurrent.Semaphore; public class TurnTakingWithSemaphore { private static final Semaphore semaphoreA = new Semaphore(1); // A先执行 private static final Semaphore semaphoreB = new Semaphore(0); public static void main(String[] args) { Runnable taskA = () -> { try { for (int i = 0; i < 5; i++) { semaphoreA.acquire(); // 获取A的许可 System.out.println("Thread-A: " + i); semaphoreB.release(); // 释放B的许可 } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }; Runnable taskB = () -> { try { for (int i = 0; i < 5; i++) { semaphoreB.acquire(); // 获取B的许可 System.out.println("Thread-B: " + i); semaphoreA.release(); // 释放A的许可 } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }; new Thread(taskA).start(); new Thread(taskB).start(); } }
原理:
- 初始化:A有1个许可(可执行),B有0个许可(阻塞)。
- A执行 → 释放B的许可 → B执行 → 释放A的许可 → 循环。
️ 关键注意事项
- 避免死锁:
- 确保每个wait()/await()都有对应的唤醒。
- 锁释放:在finally块中释放显式锁(ReentrantLock)。
- 性能考量:
- 轻量级场景用synchronized,高并发场景用ReentrantLock。
- 信号量适用于多阶段复杂同步。
- 线程中断处理:
- 捕获InterruptedException并恢复中断状态(Thread.currentThread().interrupt())。
- 可见性保证:
- 共享变量(如isThreadATurn)需用volatile修饰(或通过锁保证可见性)。
总结建议
| 方案 | 适用场景 | 性能 | 复杂度 |
|---|---|---|---|
| synchronized + 等待通知 | 简单交替逻辑 | 中等 | |
| ReentrantLock + Condition | 高并发、精准控制 | 高 | |
| Semaphore | 多许可控制(如超过2个线程轮流) | 中等 |
推荐选择:
- 新手优先使用 synchronized 方案(简洁安全)。
- 生产环境推荐 ReentrantLock + Condition(性能最优)。
引用说明:
- Java并发模型基于《Java并发编程实战》(Brian Goetz等)。
- ReentrantLock 设计参考Oracle官方文档Java 17 Lock API。
- 线程同步原则遵循JLS(Java语言规范)第17章内存模型。