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
相关产品推荐
相关产品推荐

