多同步方法线程顺序控制问题:为何无法按A→B→C顺序循环打印三次?
解决你的Java多线程顺序打印问题
嘿,我来帮你梳理下代码里的问题,以及怎么修复它~
你的核心问题是没有一个明确的状态标记来管控线程的执行顺序,再加上notify()是随机唤醒等待线程的,这就导致了输出顺序乱掉。咱们一步步来看:
你遗漏的关键逻辑
- 缺少一个共享的状态变量,用来标记当前该哪个线程发言
- 每个线程拿到锁后,不能直接就打印,得先确认是不是轮到自己了
- 用
notifyAll()替代notify()会更可靠,这样能唤醒所有等待的线程,让它们自己判断是否该执行
修正后的代码
public class Chat { // 用枚举定义发言顺序,清晰直观 enum Speaker { A, B, C } // 初始设置为A先发言 private Speaker currentSpeaker = Speaker.A; synchronized void chatA(){ for(int i = 0; i<3; i++) { // 循环等待,直到轮到自己 while(currentSpeaker != Speaker.A) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("A"); // 切换到下一个发言者B currentSpeaker = Speaker.B; // 唤醒所有等待线程,让它们检查状态 notifyAll(); } } synchronized void chatB(){ for(int i=0; i<3; i++) { while(currentSpeaker != Speaker.B) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("B"); currentSpeaker = Speaker.C; notifyAll(); } } synchronized void chatC(){ for(int i=0; i<3; i++) { while(currentSpeaker != Speaker.C) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("C"); // 切换回A,完成一轮循环 currentSpeaker = Speaker.A; notifyAll(); } } public static void main(String[] args){ Chat chat = new Chat(); Thread t1 = new Thread(chat::chatA); Thread t2 = new Thread(chat::chatB); Thread t3 = new Thread(chat::chatC); t1.start(); t2.start(); t3.start(); } }
为什么这样改?
- 状态变量
currentSpeaker:相当于一个“发言令牌”,只有拿到令牌的线程才能执行打印操作 while循环检查令牌:用while而不是if是为了防止虚假唤醒——线程可能会在没被正确通知的情况下醒来,这时候得再确认一遍令牌是不是自己的notifyAll()唤醒所有线程:这样所有等待的线程都会醒来检查令牌,只有持有正确令牌的线程会继续执行,保证了顺序不会乱- 切换令牌:每个线程打印完后,把令牌传给下一个线程,形成A→B→C→A的循环,完美实现各打印3次的需求
现在运行这段代码,就能得到你想要的A、B、C依次打印3次的结果啦~
内容的提问来源于stack exchange,提问作者armanruhit
相关产品推荐
相关产品推荐

