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

Java中如何实现两个线程交替依次执行?

实现两个线程严格交替执行的方案

我尝试让两个线程交替执行,但实际运行时线程1会连续执行20-30次,之后线程2再连续执行20-30次。以下是我的代码:

static int shared = 0;
public static void main(String[] args) {
    ReentrantLock lock = new ReentrantLock();
    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 1; i <= 1000; ++i){
                if (true){
                    lock.lock();
                    System.out.println("thread"+ 1 +" : shared = " + shared++);
                    lock.unlock();
                }
            }
        }
    });
    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 1; i <= 1000; ++i){
                if (true){
                    lock.lock();
                    System.out.println("thread"+ 2 +" : shared = " + shared++);
                    lock.unlock();
                }
            }
        }
    });
    t1.start();
    t2.start();
}

请问如何修改才能实现线程1执行一次后线程2执行一次,如此交替运行?

为什么原代码达不到交替效果?

你用的ReentrantLock只解决了线程互斥的问题——保证同一时间只有一个线程能操作共享变量,但它管不了线程的调度顺序。当一个线程释放锁后,操作系统的调度器很可能会再次选中它(毕竟线程上下文切换有开销,调度器倾向于复用当前活跃的线程),所以就出现了连续执行几十次的情况。

要实现严格的交替,我们需要让线程在完成任务后主动“叫醒”另一个线程,同时自己进入等待状态。下面给你两种靠谱的实现方案:


方案1:用ReentrantLock + Condition(推荐)

Condition是ReentrantLock的配套工具,可以实现更精细的等待/通知控制,每个线程对应一个等待队列,精准唤醒目标线程:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class AlternatingThreads {
    static int shared = 0;
    private static final ReentrantLock lock = new ReentrantLock();
    // 为两个线程分别创建条件变量,用于等待和唤醒
    private static final Condition t1Wait = lock.newCondition();
    private static final Condition t2Wait = lock.newCondition();
    // 标记当前轮到哪个线程执行:true=线程1,false=线程2
    private static boolean isT1Turn = true;

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            for (int i = 1; i <= 1000; ++i) {
                lock.lock();
                try {
                    // 不是自己的回合就等待,用while防止虚假唤醒
                    while (!isT1Turn) {
                        t1Wait.await();
                    }
                    // 执行任务
                    System.out.println("thread1 : shared = " + shared++);
                    // 切换回合标记
                    isT1Turn = false;
                    // 唤醒线程2
                    t2Wait.signal();
                } catch (InterruptedException e) {
                    // 中断后重置状态,避免后续逻辑异常
                    Thread.currentThread().interrupt();
                } finally {
                    lock.unlock();
                }
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 1; i <= 1000; ++i) {
                lock.lock();
                try {
                    while (isT1Turn) {
                        t2Wait.await();
                    }
                    System.out.println("thread2 : shared = " + shared++);
                    isT1Turn = true;
                    // 唤醒线程1
                    t1Wait.signal();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    lock.unlock();
                }
            }
        });

        t1.start();
        t2.start();
    }
}

方案2:用synchronized + wait()/notify()

如果不想用Lock体系,用Java原生的synchronized配合等待通知机制也能实现,原理和上面一致:

public class AlternatingThreadsSync {
    static int shared = 0;
    private static final Object lock = new Object();
    private static boolean isT1Turn = true;

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            for (int i = 1; i <= 1000; ++i) {
                synchronized (lock) {
                    try {
                        while (!isT1Turn) {
                            lock.wait();
                        }
                        System.out.println("thread1 : shared = " + shared++);
                        isT1Turn = false;
                        lock.notify();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 1; i <= 1000; ++i) {
                synchronized (lock) {
                    try {
                        while (isT1Turn) {
                            lock.wait();
                        }
                        System.out.println("thread2 : shared = " + shared++);
                        isT1Turn = true;
                        lock.notify();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        });

        t1.start();
        t2.start();
    }
}

关键注意点

  • 必须用while判断执行条件:不能用if,因为线程可能会被“虚假唤醒”(没有被主动通知就从等待中返回),while能确保再次检查条件,避免错误执行。
  • 中断处理:捕获InterruptedException后,一定要调用Thread.currentThread().interrupt()重置中断状态,否则后续依赖中断状态的逻辑会出错。

内容的提问来源于stack exchange,提问作者TRose

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:02:49