Java 8 CompletableFuture惰性计算控制

Dar*_*ake 5 java lazy-evaluation java-8 completable-future

我有一个关于CompletableFuture及其对延迟计算的可能用法的问题。

似乎可以很好地替代RunnableFuture此任务,因为可以轻松创建任务链并对每个链链接进行完全控制。我仍然发现很难控制何时准确进行计算。

如果我只是创建一个CompletableFuturewith supplyAssync方法或类似的方法,那就可以了。它耐心等待我调用getjoin计算方法。但是,如果我试图使与实际链whenComposehandle或任何其他方法,评价将立即启动,这是非常令人沮丧的。

当然,我总是可以在链的开头放置一些阻止程序任务,并在准备开始计算时释放该阻止程序,但这似乎有点难看。有人知道如何控制CompletableFuture实际运行的时间。

Sam*_*Sam 6

RunnableFuture和之间存在概念上的差异,CompletableFuture您在这里忽略了这一点。

  • RunnableFuture实现将任务作为输入并保留它。当您调用该方法时,它会运行任务run
  • ACompletableFuture不保留任务。它只知道任务的结果。它具有三种状态:完成未完成异常完成(失败)。

CompletableFuture.supplyAsync是一个工厂方法,它给你一个不完整的CompletableFuture. 它还会安排一个任务,当该任务完成时,会将其结果传递给 的CompletableFuture方法complete。换句话说,supplyAsync交给你的 future 对任务一无所知,也无法控制任务何时运行。

CompletableFuture要按照您描述的方式使用 a ,您需要创建一个子类:

public class RunnableCompletableFuture<T> extends CompletableFuture<T> implements RunnableFuture<T> {
    private final Callable<T> task;

    public RunnableCompletableFuture(Callable<T> task) {
        this.task = task;
    }

    @Override
    public void run() {
        try {
            complete(task.call());
        } catch (Exception e) {
            completeExceptionally(e);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


the*_*472 5

CompletableFuture 是一种推送式设计,即将结果在可用时立即推送到相关任务。这也意味着本身没有被消耗的侧链仍然会被执行,这可能会产生副作用。

您想要的是一种拉式设计,其中祖先只会在其数据被消耗时被拉入。这将是一个根本不同的设计,因为非消耗树的副作用永远不会发生。

当然,如果有足够的扭曲,CF 可以做你想做的事,但你应该看看 fork-join 框架,它允许你只运行你依赖的计算而不是推低结果。