【问题标题】:How to execute a CompletableFuture asynchronously如何异步执行 CompletableFuture
【发布时间】:2020-05-06 05:53:22
【问题描述】:

我创建了一个实现异步重试模式的方法。实际上,我希望当我调用此方法时,请求应该在一个单独的线程中处理,并且应该延迟重试

private <R> CompletableFuture<R> withRetryRequest(Supplier<CompletableFuture<R>> supplier, int maxRetries) {
        CompletableFuture<R> f = supplier.get();
        for (int i = 0; i < maxRetries; i++) {
            f = f.thenApply(CompletableFuture::completedFuture)
                    .exceptionally(t -> {
                        try {
                            Thread.sleep(10 * 1000);
                        } catch (Exception exp) {
                            log.log(Level.SEVERE, "Error while delay executing", exp);
                        }
                        return supplier.get();
                    })
                    .thenCompose(Function.identity());
        }
        return f;
    }

这里是调用者部分:

ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(PropUtil.getPropUtil().THREAD_POOL_SIZE);

CompletableFuture<Boolean> retry = this.withRetryRequest(() -> runDoorOpenProcedure(req), req.getRetryCount());

final CompletableFuture<Boolean> retryFinal = retry;
CompletableFuture<CompletableFuture<Boolean>> retryRes = CompletableFuture.supplyAsync(() -> retryFinal, executor);
Boolean success = retry.get().join();

但似乎调用根本不是异步的。我在这里做错了什么,有人可以看看这个吗?

【问题讨论】:

  • 你怎么知道它不叫异步?你必须在CompletableFuture.supplyAsyncretry.get().join() 之间做点什么,目前,你的主线程正在等待。在supplyAsync之后打印一些东西
  • 或者你可以打印withRetryRequest里面的thread_id。 Thread currentThread = Thread.currentThread(); System.out.println("thread id:" + currentThread.getId());
  • 我已经在 withRetryRequest 中打印了 ThreadId,它似乎是所有请求的同一个线程。 “你怎么知道它不叫异步?”我从 https 请求中调用此代码,并且每次 HTTP 调用都等到重试完成,所以这总体上不是异步的。我没有在我做错的地方得到这个。
  • 我明白你的意思。你的 HTTP 请求等待的原因是因为你 retry.get().join();。我觉得你需要另辟蹊径来写这个逻辑,CompletedFuture 不适合这种场景。
  • 每个 HTTP 请求都是通过发送请求并等待结果来工作的。要使其异步,您需要对设置进行根本更改,例如在浏览器中运行脚本以处理异步结果。

标签: java java-8 completable-future threadpoolexecutor


【解决方案1】:

检查这个:https://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/

CompletedFuture适用于一些场景,比如你想把你的任务拆分成并行的,你还需要任务结果继续或者聚合,然后你的主线程一直等到你从所有的子任务中得到所有的结果。子任务运行时主线程被阻塞。

如果您不需要异步任务的结果,您可以创建Thread 并将它们放入ThreadPool,然后返回。

【讨论】:

    猜你喜欢
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多