核心Java中如何让长时间等待的线程运行?线程顺序打印问题求助
解决多线程依次打印1、2、3时的线程等待问题
咱们一步步拆解你代码里的问题,然后给出完整的修复方案:
原代码的核心问题
- 条件判断用
if而非while:线程被notify()唤醒后可能遇到「虚假唤醒」(系统层面的意外唤醒),如果只用if判断,会直接跳过检查执行后续逻辑,导致顺序混乱或者线程卡死。 - 未处理不满足条件的情况:比如Thread2拿到锁后,发现当前数字不是1,但代码里没有让它
wait()释放锁,要么会一直循环占用锁,要么进入错误的逻辑。 notify()的局限性:notify()只会随机唤醒一个等待的线程,如果唤醒的不是下一个该执行的线程,就会导致那个线程再次wait(),而正确的线程没被唤醒,最终所有线程都陷入等待。- 缺少Thread3的完整逻辑:原代码里完全没处理Thread3的分支,它拿到锁后根本不知道该做什么。
修复后的完整代码
首先定义共享的锁对象和计数器:
import java.util.concurrent.atomic.AtomicInteger; public class OrderedPrinting { private static final Object lock = new Object(); private static final AtomicInteger counter = new AtomicInteger(0); public static void main(String[] args) { Thread thread1 = new Thread(new PrintTask(0), "Thread1"); Thread thread2 = new Thread(new PrintTask(1), "Thread2"); Thread thread3 = new Thread(new PrintTask(2), "Thread3"); thread1.start(); thread2.start(); thread3.start(); } static class PrintTask implements Runnable { private final int targetState; public PrintTask(int targetState) { this.targetState = targetState; } @Override public void run() { while (true) { synchronized (lock) { // 用while循环检查条件,处理虚假唤醒 while (counter.get() != targetState) { try { lock.wait(); } catch (InterruptedException e) { // 线程被中断时,正确退出 Thread.currentThread().interrupt(); return; } } // 打印当前数字和线程名 int num = counter.incrementAndGet(); System.out.print(num + "(" + Thread.currentThread().getName() + ") "); // 唤醒所有等待的线程,让它们重新检查条件 lock.notifyAll(); // 打印完3后重置计数器,实现循环打印 if (num == 3) { counter.set(0); System.out.println(); // 换行分隔每次循环 try { // 可选:放慢速度,方便观察效果 Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } } } } } } }
关键修复点说明
- 用
while替代if判断条件:每次线程被唤醒后,都会重新检查当前计数器是否符合自己的执行条件,彻底避免虚假唤醒带来的问题。 - 不满足条件时调用
wait():释放锁,让其他线程有机会获取锁并执行,不会出现某线程一直占用锁的情况。 - 使用
notifyAll()唤醒所有线程:确保所有等待的线程都能被唤醒,然后各自检查条件,找到下一个该执行的线程,不会出现唤醒错误线程导致全部卡死的情况。 - 统一的任务封装:把打印逻辑封装成
PrintTask,通过构造参数传入每个线程对应的目标状态,代码更简洁易维护。 - 处理线程中断:当线程被中断时,正确退出并标记中断状态,避免资源泄漏。
这样修改后,三个线程就会严格按照Thread1→Thread2→Thread3的顺序依次打印1、2、3,循环往复,不会出现线程长时间等待无法运行的问题。
内容的提问来源于stack exchange,提问作者Vaithilingam K
相关产品推荐
相关产品推荐

