如何强制线程按顺序执行?多线程按序打印字母求助
如何强制线程按顺序循环打印字母表
我明白你现在的困扰——四个线程打印字母时总是乱序,想要让它们严格按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; } } } } }
关键细节说明
- 共享锁:所有线程用同一个
lock对象同步,确保wait和notifyAll能在同一个等待池里协调线程。 - while循环检查:用
while而不是if判断回合,是为了防止虚假唤醒——线程被唤醒后,可能当前回合已经被其他线程抢走,需要再次确认。 - 回合更新与唤醒:打印完成后立即更新
currentTurn,再唤醒所有线程,确保下一个线程能及时抢到执行权。
运行这段代码后,就会严格按照t1→t2→t3→t4→t1→t2...的顺序循环打印所有字母啦。
内容的提问来源于stack exchange,提问作者imalogginin
相关产品推荐
相关产品推荐

