简体   繁体   English

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

[英]How to reinitialize inside synchronized block in Java?

I have a s3client which uses password with 60 days rotation policy.我有一个 s3client,它使用具有 60 天轮换策略的密码。 For that, we have a single s3client object being used but when the password rotates, all threads start giving exceptions.为此,我们使用了一个 s3client object,但是当密码轮换时,所有线程都开始出现异常。 I want to catch and make sure only 1 of the threads reinitialize Client and others do nothing inside synchronized block.我想捕获并确保只有 1 个线程重新初始化客户端,而其他线程在同步块内什么都不做。 Can't figure out a way to do so.想不出这样做的方法。

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;
}

You didn't share the code that does the actual error handling / trigger the re-initialize.您没有共享执行实际错误处理/触发重新初始化的代码。 I assume that you call the method on any occuring IOException.我假设您在任何发生的 IOException 上调用该方法。 To avoid that eg temporal.network problems lead to thousands or millions of unwnated re-initializations I would suggest to specify a minimal time between two re-initializations.为避免例如 temporal.network 问题导致数以千计或数百万次意外的重新初始化,我建议指定两次重新初始化之间的最短时间。 This helps also to make the code simpler:这也有助于使代码更简单:

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;
    }
  }
}

I assume that the s3Client field is volatile and the s3Client implementation is thread-safe.我假设 s3Client 字段是易变的并且 s3Client 实现是线程安全的。 If s3Client should not be volatile and access to it should already be synchronized by another object, then replace YourClass.class in the synchronized statement with that object.如果 s3Client 不应该是易失的并且对它的访问应该已经被另一个 object 同步,那么将同步语句中的 YourClass.class 替换为该 object。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM