如何创建依次执行的3个线程?能否仅用notify/wait/synchronized无标志实现?
实现无标志位的线程顺序循环输出
当然可以实现!不用显式标志位(比如int、boolean这类状态变量)的话,我们可以利用线程实例本身作为隐性的执行标识,结合synchronized、wait()和notifyAll()来保证三个线程按顺序循环输出,同时避免竞态条件。
核心思路
- 定义一个共享的调度器对象,用来管理当前允许执行的线程——这里不用传统标志位,而是直接用线程实例本身作为判断依据。
- 每个线程在执行前,先在调度器的同步方法里检查:当前允许执行的线程是不是自己?如果不是就进入等待;如果是,就执行输出逻辑。
- 线程执行完成后,更新调度器里的“当前允许线程”为下一个线程,然后唤醒所有等待的线程,让它们重新检查是否轮到自己。
完整代码实现
public class SequentialWorkers { public static void main(String[] args) { // 先创建三个工作线程 WorkerThread worker1 = new WorkerThread("worker1"); WorkerThread worker2 = new WorkerThread("worker2"); WorkerThread worker3 = new WorkerThread("worker3"); // 初始化调度器,指定第一个执行的线程是worker1 ThreadScheduler scheduler = new ThreadScheduler(worker1); // 给每个线程绑定调度器和下一个要执行的线程 worker1.init(scheduler, worker2); worker2.init(scheduler, worker3); worker3.init(scheduler, worker1); // 启动所有线程 worker1.start(); worker2.start(); worker3.start(); } } // 工作线程类 class WorkerThread extends Thread { private ThreadScheduler scheduler; private Thread nextWorker; public WorkerThread(String name) { super(name); } // 初始化调度器和下一个线程 public void init(ThreadScheduler scheduler, Thread nextWorker) { this.scheduler = scheduler; this.nextWorker = nextWorker; } @Override public void run() { try { // 无限循环执行,直到线程被中断 while (!Thread.currentThread().isInterrupted()) { // 等待轮到自己执行 scheduler.waitForTurn(this); // 输出当前线程名 System.out.println(getName()); // 模拟工作耗时(可选,去掉不影响逻辑) Thread.sleep(300); // 把执行权交给下一个线程 scheduler.passTurn(nextWorker); } } catch (InterruptedException e) { // 处理中断,恢复中断状态 Thread.currentThread().interrupt(); System.out.println(getName() + " 已被中断"); } } } // 线程调度器,负责管理执行顺序 class ThreadScheduler { // 当前允许执行的线程(用线程实例代替传统标志位) private Thread currentWorker; public ThreadScheduler(Thread firstWorker) { this.currentWorker = firstWorker; } // 等待轮到当前线程执行 public synchronized void waitForTurn(Thread worker) throws InterruptedException { // 必须用while循环,防止虚假唤醒(线程被唤醒后状态可能已变化) while (currentWorker != worker) { wait(); } } // 将执行权传递给下一个线程 public synchronized void passTurn(Thread nextWorker) { currentWorker = nextWorker; // 用notifyAll()而非notify(),确保所有等待的线程都能检查状态 // 避免notify()随机唤醒错误线程导致的执行停滞 notifyAll(); } }
关键细节说明
- 避免虚假唤醒:用
while循环而非if检查当前线程是否可执行。因为线程可能被虚假唤醒(没有被notify()唤醒就从wait()返回),此时状态已经不符合,必须重新等待。 - 用notifyAll()而不是notify():如果用
notify(),可能随机唤醒一个不应该执行的线程,导致该线程再次wait(),而正确的线程继续等待。notifyAll()会唤醒所有等待的线程,它们都会重新检查状态,确保正确的线程能获取执行权。 - 线程安全的状态更新:所有对
currentWorker的读写都在synchronized方法里,避免了竞态条件——多个线程不会同时修改或读取这个变量。
内容的提问来源于stack exchange,提问作者Даниил Агеев
相关产品推荐
相关产品推荐

