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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 06:44:53