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

并行运行测试时如何实现日志横幅仅在日志文件中输出一次

现有实现的问题

你当前的写法存在竞态条件漏洞,并非100%可靠:

  • 多个并行线程可能同时判断!isDone为true,在第一个线程修改isDone为true之前,多个线程都能进入判断块,即便doOnlyOnce加了synchronized修饰,也只会让这些线程串行执行方法,还是会出现横幅多次打印的问题,你当前没有复现只是偶发情况。
  • 你把修改isDone的操作放在了doOnlyOnce调用之前,还会出现标记已经设为true,但横幅还没打印完成的问题,不符合预期执行顺序。

优化后的可靠实现

可以用标准的双重检查锁定模式保证逻辑仅执行一次,同时兼顾并发性能:

class Foo {
  private static volatile Boolean isDone = false;
  // 单独的锁对象,避免锁范围扩散
  private static final Object LOCK = new Object();

  public Foo() {
    // 第一层无锁检查,高并发场景下性能更好
    if (!isDone) {
      // 加类级锁,保证同一时间只有一个线程进入同步块
      synchronized (LOCK) {
        // 第二层校验,避免多个线程等待锁后重复执行逻辑
        if (!isDone) {
          // 先执行打印逻辑,完成后再修改标记
          doOnlyOnce();
          isDone = true;
        }
      }
    }
  }

  private void doOnlyOnce() {
    // 打印日志横幅的具体逻辑
  }
}

适配Log4j2的原生方案

针对你当前的技术栈,其实不需要自己实现同步逻辑,直接利用Log4j2的生命周期回调就能实现横幅仅打印一次:
自定义实现Log4j2的LoggerContextListener接口,重写contextStarted方法写入横幅逻辑,再将监听器注册到Log4j2配置中。LoggerContext全局仅会初始化一次,天然避免并行执行重复打印的问题,不需要额外加锁,性能和可靠性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 02:42:01