在编写Java CompletableFutures时使用哪个执行程序?

ste*_*bot 5 java completable-future

我在某个存储库类上有一个返回a的方法CompletableFuture.完成这些期货的代码使用阻止的第三方库.我打算有一个单独的有限Executor,这个存储库类将用于进行这些阻塞调用.

这是一个例子:

public class PersonRepository {
    private Executor executor = ...
    public CompletableFuture<Void> create(Person person) {...}
    public CompletableFuture<Boolean> delete(Person person) {...}
}
Run Code Online (Sandbox Code Playgroud)

我的应用程序的其余部分将组成这些未来,并对结果做一些其他事情.当被提供给这些其他功能thenAccept,thenCompose,whenComplete,等等,我不想让他们对运行Executor储备库.

另一个例子:

public CompletableFuture<?> replacePerson(Person person) {
    final PersonRepository repo = getPersonRepository();
    return repo.delete(person)
        .thenAccept(existed -> {
            if (existed) System.out.println("Person deleted"));
            else System.out.println("Person did not exist"));
        })
        .thenCompose(unused -> {
            System.out.println("Creating person");
            return repo.create(person);
        })
        .whenComplete((unused, ex) -> {
            if (ex != null) System.out.println("Creating person");
            repo.close();
        });
}
Run Code Online (Sandbox Code Playgroud)

JavaDoc声明:

为非异步方法的依赖完成提供的动作可以由完成当前CompletableFuture的线程执行,或者由完成方法的任何其他调用者执行.

侧问题:为什么会出现一个这里?在什么情况下,还有另一个完成方法的调用者无法完成当前的未来?

主要问题:如果我想要通过与存储库使用println的不同的方式执行所有Executor操作,我需要使用哪些方法进行异步并手动提供执行程序?

显然thenAccept需要改变,thenAcceptAsync但我不确定那一点.

替代问题:哪个线程完成了返回的未来thenCompose

我的猜测是,无论线程完成从函数参数返回的未来是什么.换句话说,我还需要whenComplete改为whenCompleteAsync.

也许我已经过度复杂了,但感觉它可能变得非常棘手.我需要非常关注所有这些未来的来源.同样从设计的角度来看,如果我返回未来,我如何阻止呼叫者使用我的执行者?感觉它破坏了封装.我知道Scala中的所有转换函数都采用隐式ExecutionContext,这似乎解决了所有这些问题.

joh*_*384 5

问题:如果您将中间CompletionStage值分配给变量并在其上调用方法,则它将在同一个线程上执行.

主要问题:只有第一个,所以更改thenAcceptthenAcceptAsync- 以下所有将在用于接受的线程上执行其步骤.

备选问题:完成未来的线程thenCompose与用于撰写的线程相同.

您应该将CompletionStages视为在同一线程上快速连续执行的步骤(通过按顺序应用函数),除非您特别希望使用async在不同的线程上执行该步骤.然后,在该新线程上完成所有后续步骤.

在您当前的设置中,步骤将执行如下:

Thread-1: delete, accept, compose, complete
Run Code Online (Sandbox Code Playgroud)

第一个接受异步,它变为:

Thread-1: delete
Thread-2: accept, compose, complete
Run Code Online (Sandbox Code Playgroud)

至于你的最后一个问题,关于你的呼叫者使用的同一个线程,如果他们添加了额外的步骤 - 我认为除了不返回a CompletableFuture,而是正常之外你还能做很多事情Future.


Joe*_*e C 5

仅根据我在玩弄它时的经验观察,执行这些非异步方法的线程将取决于哪个先发生,thenCompose它本身或Future.

如果thenCompose首先完成(在您的情况下几乎可以肯定),则该方法将在执行Future任务的同一线程上运行。

如果您背后的任务Future首先完成,则该方法将立即在调用线程上运行(即根本没有执行程序)。