Java多线程:如何实现线程按顺序单次执行run方法后循环执行?
实现按顺序循环执行的多线程协作机制
这种让每个动作对应独立线程、按固定顺序循环执行的需求,本质是要解决多线程间的顺序同步+轮次循环问题。我给你设计一个SequentialCycleCoordinator类来做全局调度,配合每个动作线程就能完美实现你的想法。
核心设计思路
我们需要两个关键同步组件来实现这个机制:
- CountDownLatch:控制每个步骤的执行时机,确保只有前一个步骤完成后,下一个步骤的线程才能启动。
- CyclicBarrier:当所有线程完成一轮动作后,统一重置状态,开启下一轮循环。
完整实现代码
协调器类 SequentialCycleCoordinator
这个类负责管理步骤顺序和轮次切换,是整个机制的核心:
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.atomic.AtomicInteger; public class SequentialCycleCoordinator { // 当前执行的步骤序号(从0开始) private final AtomicInteger currentStep = new AtomicInteger(0); // 总动作数量 private final int totalSteps; // 等待所有线程完成一轮的屏障,完成后触发重置逻辑 private final CyclicBarrier roundBarrier; // 每个步骤对应的 latch,控制该步骤线程的执行时机 private final CountDownLatch[] stepLatches; public SequentialCycleCoordinator(int totalSteps) { this.totalSteps = totalSteps; this.roundBarrier = new CyclicBarrier(totalSteps, this::resetForNextRound); this.stepLatches = new CountDownLatch[totalSteps]; // 初始化所有步骤的 latch for (int i = 0; i < totalSteps; i++) { stepLatches[i] = new CountDownLatch(1); } // 第一个步骤默认放行,启动第一轮 stepLatches[0].countDown(); } // 让当前线程等待,直到轮到自己的步骤执行 public void awaitTurn(int stepIndex) throws InterruptedException { stepLatches[stepIndex].await(); } // 当前步骤执行完成,通知下一个步骤或等待一轮结束 public void signalNextStep(int stepIndex) { int nextStep = (stepIndex + 1) % totalSteps; // 如果是最后一步,先等所有线程到屏障,再触发重置 if (stepIndex == totalSteps - 1) { try { roundBarrier.await(); } catch (Exception e) { Thread.currentThread().interrupt(); // 中断异常时标记线程中断状态 } } else { // 非最后一步,直接放行下一个步骤 stepLatches[nextStep].countDown(); } } // 一轮完成后,重置所有状态,准备下一轮循环 private void resetForNextRound() { currentStep.set(0); // 重新初始化所有 latch,并放行第一个步骤 for (int i = 0; i < totalSteps; i++) { stepLatches[i] = new CountDownLatch(1); } stepLatches[0].countDown(); } }
动作线程类 ActionThread
每个动作对应一个线程,通过协调器控制自己的执行时机:
public class ActionThread extends Thread { private final int stepIndex; // 当前线程对应的步骤序号 private final SequentialCycleCoordinator coordinator; private final Runnable action; // 要执行的动作逻辑 public ActionThread(int stepIndex, SequentialCycleCoordinator coordinator, Runnable action) { this.stepIndex = stepIndex; this.coordinator = coordinator; this.action = action; } @Override public void run() { try { // 循环执行,直到线程被中断 while (!Thread.currentThread().isInterrupted()) { // 等待协调器通知自己可以执行 coordinator.awaitTurn(stepIndex); // 执行具体动作 action.run(); // 通知协调器当前步骤完成,触发下一步或等待一轮结束 coordinator.signalNextStep(stepIndex); } } catch (InterruptedException e) { // 捕获中断,标记线程状态,优雅退出 Thread.currentThread().interrupt(); System.out.println("动作线程" + stepIndex + "已中断退出"); } } }
使用示例
public class Main { public static void main(String[] args) throws InterruptedException { int totalActions = 3; // 假设有3个按顺序执行的动作 SequentialCycleCoordinator coordinator = new SequentialCycleCoordinator(totalActions); // 创建并启动每个动作线程 new ActionThread(0, coordinator, () -> { System.out.println("执行动作1 | 线程:" + Thread.currentThread().getName()); try { Thread.sleep(500); } catch (InterruptedException ignored) {} // 模拟动作耗时 }).start(); new ActionThread(1, coordinator, () -> { System.out.println("执行动作2 | 线程:" + Thread.currentThread().getName()); try { Thread.sleep(300); } catch (InterruptedException ignored) {} }).start(); new ActionThread(2, coordinator, () -> { System.out.println("执行动作3 | 线程:" + Thread.currentThread().getName()); try { Thread.sleep(400); } catch (InterruptedException ignored) {} }).start(); // 让程序运行10秒后中断所有线程 Thread.sleep(10000); Thread.getAllStackTraces().keySet().stream() .filter(t -> t.getName().startsWith("Thread-")) .forEach(Thread::interrupt); } }
关键逻辑解释
- 步骤顺序控制:每个线程通过
awaitTurn等待自己的步骤latch被放行,只有前一个步骤执行完成后,才会调用signalNextStep放行下一个步骤的latch,严格保证顺序。 - 轮次循环:当最后一个步骤完成后,会触发
CyclicBarrier的等待逻辑,等所有线程都到达屏障后,调用resetForNextRound重置所有latch,放行第一个步骤,开启新的一轮。 - 线程安全:使用
AtomicInteger管理当前步骤序号,CountDownLatch和CyclicBarrier都是线程安全的同步组件,确保多线程环境下的顺序正确性。
注意事项
- 记得处理
InterruptedException,保证线程可以优雅退出,避免资源泄漏。 - 如果你的动作可能抛出异常,建议在
action.run()外围增加try-catch,避免单个线程异常导致整个循环中断。 - 可以根据需求扩展协调器,比如添加超时等待、暂停/继续功能等。
内容的提问来源于stack exchange,提问作者StefanoN
相关产品推荐
相关产品推荐

