执行CompletableFuture的多个thenAccept块的顺序是什么 [英] What is the order in which multiple thenAccept blocks of a CompletableFuture are executed

查看:292
本文介绍了执行CompletableFuture的多个thenAccept块的顺序是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一个返回 CompletableFuture 的方法。在返回之前,此方法添加一个块 thenAccept ,该块在 CompletableFuture 完成后执行。

So I have a method that returns a CompletableFuture. Before returning, this method adds a block with thenAccept which is executed after the CompletableFuture completes.

此方法的调用者还添加了另一个块 thenAccept 。显然,这可以继续多个链式调用。

The caller of this method also adds another block with thenAccept. Obviously this can go on with multiple chained calls.

<$ c>返回 CompletionStage 的顺序$ c> thenAccept 执行调用?是否保证是添加它们的顺序?如果没有,如何保证它们按照添加顺序执行?

In what order are the CompletionStage returned by the thenAccept invocations executed? Is it guaranteed to be the order in which they are added? If not, how can one guarantee that they are executed in the order in which they are added?

PS:我根据自己的经验询问这个 CompletableFuture 文章

PS: I am asking this based on my own experience with CompletableFuture and this article

推荐答案

您正在通过链接来建模完成阶段的依赖关系。如果您将两个操作 A B 链接到另一个操作 C ,您定义关系 A→C B→C ,但之间没有任何关系一个 B 因此,它们之间没有关系,包括没有排序关系,换句话说,你甚至不能假设一个将在另一个之后运行,即

You are modelling the dependencies of completion stages by chaining them. If you chain two actions A and B to another action C, you define the relationships A → C and B → C, but no relationship between A and B and therefore, there is no relationship, including no ordering relationship, between them, in other words, you can’t even assume that one will run after the other, i.e.

CompletableFuture<String> base=CompletableFuture.supplyAsync(() -> {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
    return "source";
});
base.thenAccept(s -> {
    System.out.println("entered first consumer in "+Thread.currentThread());
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    System.out.println("leaving first consumer");
});
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
base.thenAccept(s -> {
    System.out.println("entered second consumer in "+Thread.currentThread());
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    System.out.println("leaving second consumer");
});

很可能打印类似

entered first consumer in Thread[ForkJoinPool.commonPool-worker-1,5,main]
entered second consumer in Thread[main,5,main]
leaving second consumer
leaving first consumer

当然,有没有担保。

要强制实现两个消费者之间的依赖关系,你必须适当地将它们链接起来,例如

To enforce your dependency between the two consumers, you have to chain them appropriately, e.g.

CompletableFuture<String> base=CompletableFuture.supplyAsync(() -> {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
    return "source";
});
CompletableFuture<Void> next = base.thenAccept(s -> {
    System.out.println("entered first consumer in "+Thread.currentThread());
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    System.out.println("leaving first consumer");
});
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
base.thenAcceptBoth(next, (s,ignored) -> {
    System.out.println("entered second consumer in "+Thread.currentThread());
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    System.out.println("leaving second consumer");
}).join();

这里,第二个消费者链接到 base next ,从 base 接收结果,但依赖于 next 完成(如果没有结果通常你通常不会要求 - 如果你有这样的情况,也许你想重新考虑你的设计。)

Here, the second consumer is chained to base and next, to receive the result from base, but depend on next’s completion (which you normally wouldn’t require if there is no result to pass—maybe you want to rethink your design, if you have such a scenario).

或者,您可以将第一个消费者转换为函数,它会传递该值,因此您可以通过 thenApply 链接它,以允许链接另一个 thenAccept 阶段。

Alternatively, you may convert the first Consumer to a Function which passes through the value, so you can chain it via thenApply, to allow chaining another thenAccept stage to it.

这篇关于执行CompletableFuture的多个thenAccept块的顺序是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆