有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程如何在Java中重新初始化同步块内部?

我有一个S3客户端,它使用60天轮换策略的密码。为此,我们使用了一个s3client对象,但当密码旋转时,所有线程都开始给出异常。我想捕获并确保只有一个线程重新初始化客户端,其他线程在同步块内什么都不做。我想不出办法

private static AtomicBoolean initializingS3Client = new AtomicBoolean(false);

public static AmazonS3 reinitializeAndProvideS3Client() throws Exception {
    synchronized (initializingS3Client) {
        if (initializingS3Client.compareAndSet(false, true)) {
            s3Client.shutdown();
            s3Client = createAmazonS3Client();
            initializingS3Client.notifyAll();
        } else {
            initializingS3Client.wait();
        }
    }
    return s3Client;
}

共 (1) 个答案

  1. # 1 楼答案

    您没有共享执行实际错误处理/触发重新初始化的代码。我假设您在任何发生的IOException上调用该方法。为了避免临时网络问题导致数千或数百万次未初始化的重新初始化,我建议指定两次重新初始化之间的最短时间。这也有助于简化代码:

    public YourClass {
      ...
      private static final long MIN_TIME_BETWEEN_TWO_REINITIALIZES = 60 * 1_000; // 1 min
      privat static long lastReinitialize = 0; 
    
      public static AmazonS3 reinitializeAndProvideS3Client() throws Exception {
        synchronized (YourClass.class) {
          long now = System.currentTimeInMillis();
          if (now - lastReinitialize > MIN_TIME_BETWEEN_TWO_REINITIALIZES ) {
            s3Client.shutdown();
            s3Client = createAmazonS3Client();
            lastReinitialize = now;
          } 
          return s3Client;
        }
      }
    }
    

    我假设s3Client字段是可变的,s3Client实现是线程安全的。如果s3Client不应该是易失性的,并且对它的访问应该已经被另一个对象同步,那么替换YourClass。在与该对象同步的语句中初始化