CompletableFuture的onTimeout获取提供的值,Java异步编程。

huangapple go评论68阅读模式
英文:

CompletableFuture onTimeout get the supplied value java async programming

问题

我有一个CompletableFuture链,我在其中传递一个参数(对象),链的每一步都在进行一些工作。我有一些慢的步骤,我想要用超时限制。

我注意到确实会抛出超时异常,但我不知道是哪个参数。

有没有办法在CompletableFuture API 中获取失败的doWork方法所传递的参数?

英文:

I have a completablefuture chain to which a pass a parameter (object) and each step of the chain is doing some work.
i have some slow steps which i want to limit with a timeout

what i noticed that indeed the timeout exception is thrown but i have no idea on which parameter

ComplianceCandidate candidate = candidates.poll();
            CompletableFuture<ComplianceCandidate> futureTask = CompletableFuture.supplyAsync(() -> candidate, pool)
                    .thenApply(Task1::doWork).thenApply(Task2::doWork).thenApply(Task3::doWork)
                    .thenApply(Task4::doWork).thenApply(ProblematicAndSlowTask::doWork).thenApply(AnotherProblematicTask::doWork)
                    .thenApply(Task6::doWork).thenApply(Task7::doWork).orTimeout(10, TimeUnit.SECONDS)
                    .exceptionally(ExceptionHandlerService::handle);
            completedList.add(futureTask);

is there a way in the completable future api to obtain the parameter passed to the doWork method that has failed?

答案1

得分: 1

这是不可能的,因为正如Holger在评论中解释的那样,orTimeout()仅适用于您在其上调用的CompletableFuture。对于导致该future的调用链(或者实际上是图形),没有引用。

但是,您可以通过存储它们的引用来检查所有中间的CompletableFuture

CompletableFuture<ComplianceCandidate> init = CompletableFuture.supplyAsync(() -> candidate, pool);
CompletableFuture<Result1> future1 = init.thenApply(Task1::doWork);
CompletableFuture<Result2> future2 = future1.thenApply(Task2::doWork);

CompletableFuture<Result7> future7 = future6.thenApply(Task7::doWork);
CompletionStage<Result7> future7OrTimeout = future7.orTimeout(10, TimeUnit.SECONDS);

然后逐个检查它们:

CompletableFuture<ComplianceCandidate> futureTask = future7OrTimeout.exceptionally(throwable -> {
    if (!future1.isDone() || future1.isCompletedExceptionally()) {
        System.out.println("Task1 failed");
    } else if (!future2.isDone() || future2.isCompletedExceptionally()) {
        System.out.println("Task2 failed");
    } else 
});

(我将根据您实际的调用情况,留给您自行使用循环使代码更加通用。)

英文:

This is not possible because, as Holger explained in the comments, orTimeout() applies only to the CompletableFuture you call it on. There is no reference to the call chain (or, in fact, graph) that leads to that future.

You can, however, inspect all intermediate CompletableFutures by storing their references:

CompletableFuture&lt;ComplianceCandidate&gt; init = CompletableFuture.supplyAsync(() -&gt; candidate, pool);
CompletableFuture&lt;Result1&gt; future1 = init.thenApply(Task1::doWork);
CompletableFuture&lt;Result2&gt; future2 = future1.thenApply(Task2::doWork);
…
CompletableFuture&lt;Result7&gt; future7 = future6.thenApply(Task7::doWork);
CompletionStage&lt;Result7&gt; future7OrTimeout = future7.orTimeout(10, TimeUnit.SECONDS);

and then check each of them individually:

CompletableFuture&lt;ComplianceCandidate&gt; futureTask = future7OrTimeout.exceptionally(throwable -&gt; {
	if (!future1.isDone() || future1.isCompletedExceptionally()) {
		System.out.println(&quot;Task1 failed&quot;);
	} else if (!future2.isDone() || future2.isCompletedExceptionally()) {
		System.out.println(&quot;Task2 failed&quot;)
	} else …
});

(I let it up to you to make the code more generic with loops depending on what your actual calls are)

huangapple
  • 本文由 发表于 2020年8月4日 21:24:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/63247880.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定