You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建依次执行的3个线程?能否仅用notify/wait/synchronized无标志实现?

实现无标志位的线程顺序循环输出

当然可以实现!不用显式标志位(比如int、boolean这类状态变量)的话,我们可以利用线程实例本身作为隐性的执行标识,结合synchronized、wait()和notifyAll()来保证三个线程按顺序循环输出,同时避免竞态条件。

核心思路

  1. 定义一个共享的调度器对象,用来管理当前允许执行的线程——这里不用传统标志位,而是直接用线程实例本身作为判断依据。
  2. 每个线程在执行前,先在调度器的同步方法里检查:当前允许执行的线程是不是自己?如果不是就进入等待;如果是,就执行输出逻辑。
  3. 线程执行完成后,更新调度器里的“当前允许线程”为下一个线程,然后唤醒所有等待的线程,让它们重新检查是否轮到自己。

完整代码实现

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,提问作者Даниил Агеев

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:19:11