当前位置: 首页 > 知识库问答 >
问题:

CompletableFuture的多个thenAccep块的执行顺序是什么

丰佐
2023-03-14

所以我有一个方法,返回一个完整的未来。在返回之前,该方法添加了一个带有accept的块,该块在CompletableFuture完成后执行。

此方法的调用者还添加了另一个块,其中包含和accept。显然,这可以在多个链式调用中继续进行。

thenAccess调用返回的CompletionStage以什么顺序执行?它是否保证是它们添加的顺序?如果不是,如何保证它们按照添加的顺序执行?

PS:我是根据自己对CompletableFuture和本文的经验提出这个问题的


共有1个答案

孙辰阳
2023-03-14

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

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

当然,这并不能保证。

为了加强两个消费者之间的依赖性,你必须适当地将他们联系起来,例如:。

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();

在这里,第二个消费者被链接到基础和下一个,以从基础接收结果,但取决于下一个的完成情况(如果没有结果要传递,您通常不需要这样做,如果您有这样的场景,您可能想重新考虑您的设计)。

或者,您可以将第一个消费者转换为通过值的函数,这样您可以通过应用将其链接,以允许将另一个接受阶段链接到它。

 类似资料:
  • 本文向大家介绍在a标签上的四个伪类执行顺序是什么?相关面试题,主要包含被问及在a标签上的四个伪类执行顺序是什么?时的应答技巧和注意事项,需要的朋友参考一下 执行顺序应该是: link hover active visited 因为存在样式层叠问题,所以书写顺序需要调整,把类似hover这种瞬时状态覆盖link这种常态 link visited hover active

  • 问题内容: 如果我构建自己的函数“ myfunction”并执行以下查询: 如果mytable有100万行,但是在我之后只有100行。当我执行此查询时,myfunction将执行100或100万行吗? 在这种情况下会发生什么? 问题答案: 在第一个示例中,它将仅执行100次。您可以通过在函数中添加调试调用来验证这一点: 仅针对与子句筛选器匹配的行调用该函数。但是,据我所知,这并不能保证。 在第二个

  • 问题内容: 我要查询所有10个表以从中获取用户ID,并将所有用户ID加载到HashSet中,以便可以拥有唯一的用户ID。 截至目前,它是按顺序进行的。我们转到一个表,并从中提取所有user_id并将其加载到哈希集中,然后将其存储在第二个和第三个表中并继续运行。 有什么方法可以使这个多线程的,以便他们为每个表并行地从我的表中获取数据?最后,我需要哈希集,该哈希集应具有所有10个表中的所有唯一用户ID

  • 问题内容: 是什么使线程的执行顺序不可预测?调度程序是在某个时候使用随机数还是检查系统资源,还是查看哪个线程已经等待了足够长的时间或…? 问题答案: 调度程序通常是OS的调度程序。它受许多因素的影响,包括计算机上的其他进程正在执行的操作,硬件在执行的操作(中断)等。根据操作系统的不同,我想有时可能涉及随机数,但我通常怀疑不是。多个可变时间间隔可能会重叠,这只是一种不可预测的方式。

  • 向ExecutorService对象提交任务的执行顺序是什么? 场景:让我们暂时假设Executor线程池大小为5,我已经向它提交了20个可运行任务,我们知道一次只能执行5个任务,其余的任务将在bucket中等待。所以我的问题是提交的任务以什么顺序执行。它是遵循FIFO数据结构还是从bucket中随机选取任务。 还有,有没有办法指定它应该以什么顺序执行。 例子:

  • 问题内容: 我正在尝试由两个装饰器装饰Django视图,一个装饰器用于检查登录,另一个用于检查is_active。 第一个是内置的,第二个如下: 现在,Python中的装饰器可以由内而外工作,但是以下操作不起作用: 我想首先检查用户是否已登录,如果没有,请重定向到登录页面,如果他或她已登录,则要检查他或她是否处于活动状态,如果不是,则执行重定向到。 发生的情况是,如果login_required失