依次运行异步操作

时间:2018-09-21 10:21:35

标签: java concurrency completable-future

我需要按顺序执行I / O操作(DB,I / O设备...)。

@SafeVarargs
public final CompletableFuture<Boolean> execute(final Supplier<Boolean>... methods)
{
    CompletableFuture<Boolean> future = null;

    for (Supplier<Boolean> method : methods)
    {
        if (future == null)
        {
            future = CompletableFuture.supplyAsync(method, threadPool);
        }
        else
        {
            future.thenCombineAsync(CompletableFuture.supplyAsync(method, threadPool), (result, currentResult) -> result && currentResult,
                    threadPool);
        }
    }

    return future.exceptionally(this::onException);
}

我的代码随机执行。

  1. 我该怎么做才能确保订单?
  2. 如何最终合并结果?例如,如果一切都是真的?
  3. 要在所有步骤完成后应用回调以检查结果吗?

2 个答案:

答案 0 :(得分:1)

您当前的解决方案立即调用supplyAsync(),稍后尝试合并结果。

如果要保证顺序执行,应使用thenApply()thenCompose()而不是thenCombine()

for (Supplier<Boolean> method : methods)
{
    if (future == null)
    {
        future = CompletableFuture.supplyAsync(method, threadPool);
    }
    else
    {
        future.thenApplyAsync(result -> result && method.get(), threadPool);
    }
}

请注意,如果其中一个供应商返回false,则不会调用下一个供应商的method.get(),因为&&处于短路状态。您可以使用单个&来强制调用,也可以交换参数。

这已经在最后合并了所有布尔结果。您可以在循环后在结果future上添加任何内容,例如更多thenApply()调用或阻塞join()调用以检索Boolean

请注意,也可以使用流轻松地重写此循环:

future = Arrays.stream(methods)
        .reduce(CompletableFuture.completedFuture(true),
                (f, method) -> f.thenApplyAsync(result -> result && method.get()),
                (f1, f2) -> f1.thenCombine(f2, (result1, result2) -> result1 && result2));

答案 1 :(得分:0)

您可以使用Spotify CompletableFutures库轻松做到这一点:https://github.com/spotify/completable-futures

为此,他们提供了一些非常有用的工具,例如返回allAsList的{​​{1}}。