Java线程同步实现:多Shop线程每30天协同等待方案咨询
实现周期性线程同步的可行方案
你遇到的这种周期性线程同步需求,用CyclicBarrier绝对是最优解——它就是专门为这种一组线程需要在多个节点互相等待的场景设计的,而且支持重复使用,完美适配你每30天一次的同步要求。
先说说为啥你之前的思路走不通:
- 用
Thread.join()的话,它只能等待线程完全结束,没法实现中途的周期性同步;如果拆成12次30天循环在主线程用join,线程结束后是不能重新启动的(Java线程的生命周期是不可逆的,start()方法只能调用一次),所以这个方案根本行不通。
下面是具体的实现步骤,直接可以套用:
1. 初始化CyclicBarrier
在主线程里创建CyclicBarrier实例,指定参与同步的线程数量(这里是3)。如果需要在所有线程完成当前周期后执行一些统一操作(比如打印日志、做全局统计),还可以传入一个回调任务:
// 3表示需要3个线程都到达屏障点才会一起放行 CyclicBarrier barrier = new CyclicBarrier(3, () -> { // 可选:所有线程完成当前周期后执行的统一逻辑 System.out.println("所有店铺已完成当前周期配送,全体进入下一阶段!"); });
如果不需要统一操作,直接传3就行。
2. 修改Shop类,注入CyclicBarrier
让每个Shop实例持有同一个CyclicBarrier的引用,这样所有线程都能在同一个同步点等待:
class Shop implements Runnable { private final CyclicBarrier barrier; private final String shopName; // 加个名称方便日志区分 public Shop(CyclicBarrier barrier, String shopName) { this.barrier = barrier; this.shopName = shopName; } @Override public void run() { for (int day = 0; day <= 360; ++day) { if (day % 30 == 0) { // 执行当前周期的配送操作 delivery(); System.out.println(shopName + "完成第" + (day/30) + "周期配送,等待其他店铺..."); try { // 等待所有线程到达这个同步点 barrier.await(); } catch (InterruptedException e) { // 线程被中断,恢复中断状态并终止 Thread.currentThread().interrupt(); return; } catch (BrokenBarrierException e) { // 屏障损坏(比如某线程中途异常退出),根据业务处理 System.err.println(shopName + "同步屏障失效,终止执行"); return; } } // 执行日常业务代码 doDailyBusiness(day); } } private void delivery() { System.out.println(shopName + "正在配送商品..."); // 模拟配送耗时 try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } private void doDailyBusiness(int day) { // 模拟日常业务逻辑 try { Thread.sleep(10); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }
3. 主线程启动线程
把同一个CyclicBarrier实例传给每个Shop,然后启动线程即可:
public static void main(String[] args) { CyclicBarrier barrier = new CyclicBarrier(3); Shop shop1 = new Shop(barrier, "店铺A"); Shop shop2 = new Shop(barrier, "店铺B"); Shop shop3 = new Shop(barrier, "店铺C"); List<Thread> threads = new ArrayList<>(); threads.add(new Thread(shop1)); threads.add(new Thread(shop2)); threads.add(new Thread(shop3)); for (Thread t : threads) { t.start(); } }
方案优势
- 可重复使用:每次所有线程都调用
await()后,CyclicBarrier会自动重置,等待下一次同步点,正好匹配你12次(360/30)的同步需求。 - 线程自主协调:不需要主线程介入,每个线程在完成当前周期关键操作后主动等待,逻辑清晰且解耦。
注意事项
- 一定要处理
InterruptedException:如果线程在等待时被中断,记得恢复中断状态并合理终止线程,避免业务逻辑混乱。 - 处理
BrokenBarrierException:如果某个线程在等待过程中异常退出,屏障会被标记为损坏,后续的await()都会抛出这个异常,你可以根据业务需求选择终止所有线程,或者重新创建屏障恢复同步。
内容的提问来源于stack exchange,提问作者WayOver
相关产品推荐
相关产品推荐

