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

如何强制线程按顺序执行?多线程按序打印字母求助

如何强制线程按顺序循环打印字母表

我明白你现在的困扰——四个线程打印字母时总是乱序,想要让它们严格按t1→t2→t3→t4的顺序循环执行对吧?咱们先拆解下你现有代码的问题,再给出可行的解决方案。

你的代码为什么没法保证顺序?

你当前用synchronized修饰了printletters实例方法,但每个线程对应的mythread对象是独立的,这意味着每个线程持有的锁都是自己实例的锁,四个线程的锁完全不互通。wait和notifyAll只能在同一个锁的等待池里生效,所以你的同步逻辑根本起不到跨线程协调的作用,自然会出现乱序。


解决方案:共享锁+回合标识控制

要让线程按顺序执行,核心是让所有线程共享同一个同步锁,并用一个状态变量标记当前“该谁执行”。具体思路如下:

  • 定义一个全局共享的锁对象,所有线程都用它来同步
  • 维护一个currentTurn变量,取值1-4对应四个线程的执行顺序
  • 每个线程执行前,先检查currentTurn是否等于自己的编号,不等就等待;相等就打印字母,然后更新currentTurn到下一个线程,最后唤醒所有等待的线程

修改后的完整代码

public class OrderedLetters {
    // 所有线程共享的同步锁
    private static final Object lock = new Object();
    // 当前轮到执行的线程编号(1-4循环)
    private static int currentTurn = 1;

    public static void main(String[] args) {
        char[] arr1 = new char[]{'A', 'E', 'I', 'M', 'Q', 'U', 'Y'};
        char[] arr2 = new char[]{'B', 'F', 'J', 'N', 'R', 'V', 'Z'};
        char[] arr3 = new char[]{'C', 'G', 'K', 'O', 'S', 'W'};
        char[] arr4 = new char[]{'D', 'H', 'L', 'P', 'T', 'X'};

        Thread t1 = new Thread(new OrderedThread(1, arr1));
        Thread t2 = new Thread(new OrderedThread(2, arr2));
        Thread t3 = new Thread(new OrderedThread(3, arr3));
        Thread t4 = new Thread(new OrderedThread(4, arr4));

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

    static class OrderedThread implements Runnable {
        private final int threadId;
        private final char[] letters;

        public OrderedThread(int threadId, char[] letters) {
            this.threadId = threadId;
            this.letters = letters;
        }

        @Override
        public void run() {
            for (char c : letters) {
                synchronized (lock) {
                    // 循环等待,直到当前回合属于自己(防止虚假唤醒)
                    while (currentTurn != threadId) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            // 线程被中断时,直接结束执行
                            Thread.currentThread().interrupt();
                            return;
                        }
                    }
                    // 打印当前字母
                    System.out.println(c);
                    // 更新回合:最后一个线程执行完后回到第一个
                    currentTurn = currentTurn == 4 ? 1 : currentTurn + 1;
                    // 唤醒所有等待的线程,让它们检查是否轮到自己
                    lock.notifyAll();
                }
                // 可选:添加小延迟让打印效果更直观,不加也不影响顺序
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return;
                }
            }
        }
    }
}

关键细节说明

  1. 共享锁:所有线程用同一个lock对象同步,确保wait和notifyAll能在同一个等待池里协调线程。
  2. while循环检查:用while而不是if判断回合,是为了防止虚假唤醒——线程被唤醒后,可能当前回合已经被其他线程抢走,需要再次确认。
  3. 回合更新与唤醒:打印完成后立即更新currentTurn,再唤醒所有线程,确保下一个线程能及时抢到执行权。

运行这段代码后,就会严格按照t1→t2→t3→t4→t1→t2...的顺序循环打印所有字母啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:27:44