首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Java中对CompletableFuture进行资源清理?

如何在Java中对CompletableFuture进行资源清理?
EN

Stack Overflow用户
提问于 2018-10-12 16:39:51
回答 2查看 883关注 0票数 1

我在CompletableFuture中有一段代码,如果有其他异常可以完成任务,它会执行重试。我已经向SupplierConsumer传递了一个执行任务的资源,并希望在所有任务完成后关闭这些资源(3次重试后关闭success/exception)。

下面是这段代码:

代码语言:javascript
复制
Supplier mySupplier = new MySupplier(localContext);
CompletableFuture<String> future = CompletableFuture.supplyAsync(mySupplier);
for(int j = 0; j < (retryCount - 1); j++) {
    LOGGER.debug("MySupplier accept() Retry count: "+j);
    future = future.handleAsync((value, throwable) -> throwable == null? CompletableFuture.completedFuture(value): CompletableFuture.supplyAsync(mySupplier)).thenComposeAsync(Function.identity());
}

我打算把它放在我的供应商的finally块下,但如果第一个异常发生,资源将被关闭,我需要它们来进行下两次重试。

1)如何工作?

2)是否有打印重试次数的方法,只在出现异常的情况下才打印?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-12 17:02:58

由于您似乎并不关心中间结果,因此最简单的解决方案是简单地将您的Supplier包装在另一个处理重试的the中:

代码语言:javascript
复制
class SupplierRetrier<T> implements Supplier<T> {
    private static final Logger LOGGER = LoggerFactory.getLogger(SupplierRetrier.class);
    final Supplier<T> wrappee;
    final int maxRetries;

    SupplierRetrier(Supplier<T> wrappee, int maxRetries) {
        Objects.requireNonNull(wrappee);
        if (maxRetries <= 0) {
            throw new IllegalArgumentException("maxRetries must be more than 0: " + maxRetries);
        }
        this.wrappee = wrappee;
        this.maxRetries = maxRetries;
    }

    @Override
    public T get() {
        RuntimeException lastException = null;
        for (int i = 0; i < maxRetries; i++) {
            try {
                LOGGER.info("MySupplier accept() Retry count: "+i);
                return wrappee.get();
            } catch (RuntimeException e) {
                lastException = e;
            }
        }
        throw lastException;
    }
}

然后,您可以简单地将其与以下内容一起使用:

代码语言:javascript
复制
CompletableFuture<String> future = CompletableFuture.supplyAsync(
        new SupplierRetrier<>(mySupplier, retryCount));

为了清理上下文,只需在生成的将来添加一个whenComplete()调用即可。无论将来的结果如何,都将执行此操作。

代码语言:javascript
复制
future.whenComplete((r, e) -> {
    try {
        localContext.close();
    } catch (Exception e2) {
        throw new RuntimeException("Failed to close context", e2);
    }
});
票数 0
EN

Stack Overflow用户

发布于 2018-10-13 01:01:21

1)对于资源清理,请使用whenCompletewhenCompleteAsync

2)对于重试计数,使用长度为1AtomicIntegerint[]。(无论是否抛出Exception,该值都可用)

代码语言:javascript
复制
int[] retryCounter = { 0 };
// AtomicInteger retryCounter = new AtomicInteger();

for (int i = 0; i < noOfRetries; i++)
{
  CompletableFuture<CompletableFuture<String>> handleAsync = cf.handleAsync((result, throwable) ->
    {
      if (throwable == null)
        return CompletableFuture.completedFuture(result);

      retryCounter[0]++;
      // retryCounter.incrementAndGet();

      return CompletableFuture.supplyAsync(supplier);
    });
  cf = handleAsync.thenCompose(Function.identity());
}

cf = cf.whenCompleteAsync((result, throwable) ->
  {
    System.out.println("Clean up");

    System.out.println("Retry count: " + retryCounter[0]);
    // System.out.println("Retry count: " + retryCounter.get());
  });

System.out.println("Wating for result...");
System.out.println("Result: " + cf.get());
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52775555

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档