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

如何使多线程(含ExecutorService的10线程)打印完全相同的毫秒级时间?

Hey 你好!这两个问题核心是同一个,我来给你理清楚——不仅明确告诉你可行,还帮你找出CyclicBarrier没成功的原因,再给你靠谱的实现方案~

先给结论:完全可以做到!

要让所有线程打印完全相同的毫秒时间,核心逻辑不是让线程"同时去拿时间",而是让所有线程共享同一个预先确定好的时间值——因为哪怕两个线程的调用间隔只有几纳秒,也可能刚好赶上系统毫秒时钟跳变,导致拿到不同的值。

为什么你的CyclicBarrier尝试失败了?

大概率是你写的逻辑是:让每个线程在CyclicBarrier等待结束后,自己调用System.currentTimeMillis()去拿时间。CyclicBarrier确实能让线程在同一时间点继续执行,但"同一时间点"是线程调度层面的近似,没法保证所有线程在绝对同一纳秒去调用时间方法,只要差一点点,就可能跨了毫秒边界,拿到不同的时间。

正确的实现方式

方式1:最简单的预生成时间法(推荐)

在启动任何线程之前,就在主线程先把时间拿到手,然后每个线程任务直接用这个现成的值就行,完全没并发问题:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SameTimestampPrinter {
    public static void main(String[] args) {
        // 主线程提前获取统一的毫秒时间,这时候时间就固定了
        long fixedTimestamp = System.currentTimeMillis();
        
        ExecutorService executor = Executors.newFixedThreadPool(10);
        
        for (int i = 0; i < 10; i++) {
            final int threadIndex = i + 1;
            executor.submit(() -> {
                // 直接用预先生成的时间,不用自己去拿
                System.out.printf("线程%d的打印时间:%d%n", threadIndex, fixedTimestamp);
            });
        }
        
        executor.shutdown();
    }
}

方式2:结合CyclicBarrier实现同步触发(适合需要等待所有线程就绪再输出的场景)

如果你确实需要让所有线程都准备好之后再一起输出(比如做性能测试的同步打点),可以用CyclicBarrier配合线程安全的共享变量,让所有线程等待到同一时刻,再使用预先设置好的时间:

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;

public class BarrierSyncTimestampPrinter {
    public static void main(String[] args) throws InterruptedException {
        int threadCount = 10;
        // 用原子类保证时间变量的线程可见性,避免缓存不一致
        AtomicLong sharedTimestamp = new AtomicLong();
        // 屏障数量设为线程数+1:因为主线程也要参与等待,确保所有工作线程都就绪后再设置时间
        CyclicBarrier barrier = new CyclicBarrier(threadCount + 1, () -> {
            // 所有线程都到达屏障后,由屏障的回调线程设置统一时间
            sharedTimestamp.set(System.currentTimeMillis());
        });
        
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);
        
        for (int i = 0; i < threadCount; i++) {
            final int threadIndex = i + 1;
            executor.submit(() -> {
                try {
                    // 等待所有工作线程和主线程都到达屏障
                    barrier.await();
                    // 此时时间已经被统一设置,直接打印即可
                    System.out.printf("线程%d的打印时间:%d%n", threadIndex, sharedTimestamp.get());
                } catch (Exception e) {
                    // 处理中断或异常
                    Thread.currentThread().interrupt();
                }
            });
        }
        
        // 主线程加入屏障等待,触发回调设置时间
        barrier.await();
        
        executor.shutdown();
    }
}

关键注意事项

  • ❌ 绝对不要让每个线程单独调用System.currentTimeMillis():哪怕用了同步工具,也没法保证绝对同时调用,毫秒时间可能在极短时间内变化。
  • ✅ 共享时间变量要保证线程可见性:要么用volatile修饰普通long变量,要么用AtomicLong这类原子类,避免线程读取到缓存的旧值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 09:47:31