java - Java中CompletableFuture如何进行资源清理?

标签 java multithreading java-threads completable-future

我在CompletableFuture中有一段代码,如果出现异常则执行重试,否则完成任务。我已将资源传递给 SupplierConsumer 来执行任务,并希望在所有任务完成后关闭这些资源(重试 3 次后成功/异常)。

这是一段代码:

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 block 下,但如果发生第一个异常,资源将被关闭,我需要它们来进行接下来的两次重试。

1)如何让它发挥作用?

2)还有没有办法只在异常情况下打印重试次数?

最佳答案

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

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

然后您可以简单地使用它:

CompletableFuture<String> future = CompletableFuture.supplyAsync(
        new SupplierRetrier<>(mySupplier, retryCount));

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

future.whenComplete((r, e) -> {
    try {
        localContext.close();
    } catch (Exception e2) {
        throw new RuntimeException("Failed to close context", e2);
    }
});

关于java - Java中CompletableFuture如何进行资源清理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52775555/

相关文章:

java - 如何在 Java 中将输出格式化为表格?

java - 如何从线程更新黑莓 UI 项目?

ios - swift +异步: How to execute a callback on the same thread where it was created?

java - 多个 CPU 中的线程行为

java - 如何比较变量以查看它是否是正确的类类型?

java - 使用 Apache POI 通过单元格引用字母标识符获取单元格

java - Android 中 TextView setColor 方法上的 ClassCastException

java - Thread中List的内存范围

android - OpenCV(Android) - 删除绘制的轮廓

java - 为什么我的多线程程序是顺序执行的?