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

如何在Java中重新初始化内部同步块?,java,multithreading,synchronization,Java,Multithreading,Synchronization,我有一个S3客户端,它使用60天轮换策略的密码。为此,我们使用了一个s3client对象,但当密码旋转时,所有线程都开始给出异常。我想捕获并确保只有一个线程重新初始化客户端,而其他线程在同步块内什么也不做。我想不出一个办法 private static AtomicBoolean initializingS3Client = new AtomicBoolean(false); public static AmazonS3 reinitializeAndProvideS3Client() thr

我有一个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;
}

您没有共享执行实际错误处理/触发重新初始化的代码。我假设您在发生任何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不应该是易失性的,并且对它的访问应该已经由另一个对象同步,那么用该对象替换synchronized语句中的YourClass.class