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

如何从与CompletableFutures关联的线程中发出已完成或已取消的信号?

苏健柏
2023-03-14

我读了很多关于CompletableFutures的书,他们关注的是一个事实,即CompletableFutures和Future一样,无法访问底层的计算代码。那么,如何从任何与completableFuture相关联的任务中发出complete()或cancel()信号(或者检查isCancelled(),如果您想从外部中断计算)?

编辑:让我困惑的一件事是,CF被用于替代它的可组合性或手动可设置性,在我看来,如果实现是正交的,比如:

CompletableFuture.runAsync(() -> { 
                              if(myCondition) CF_REF?.complete();
                              else            CF_REF?.exceptionally();
                           }).thenApply(() -> {
                                        if (myOtherCondition) CF_REF_2?.complete();
 (...)

以一种既不“可完成”又不“可组合”的方式设计它有什么意义?

我想找到一种方法来使用它们,就像CF使用了一个类似于假设的CompletableCallable的接口作为输入一样,但不知道如何使用。比如函数

CompletableFuture CF_REF_BIS = CompletableFuture.runAsync((CF_REF) -> { 
                                  if(myCondition) CF_REF.complete();
                                  else CF_REF.exceptionally();
                               });

CF_REF_BIS.thenApply(...)

当要计算代码时,内部执行机制将返回CF_REF_BIS引用,作为在未来计算中实际传递为CF_REF的引用,而无需访问它。

这意味着我们只需创建新的CompletableCallable(),然后在任何线程可以访问CompletableFuture信号量的地方提交n次,就可以重用一个反匿名的计算代码

例如:

CompletableFuture CF_REF = CompletableFuture.runAsync(myCompletableCallable)
             .thenApply(myCompletableCallable) //again
             .thenApply(anotherCompletableCallable); 

有没有办法满足这种需求?我忘了什么吗?我的方法有什么根本的不一致吗?Java CompletableFuture仍然是一种方便的设计吗?


共有1个答案

曹自怡
2023-03-14

看看javadoc:

CompletableFuture#complete()

如果尚未完成,请将get()和相关方法返回的值设置为给定值。

CompletableFuture#cancel()

如果尚未完成,请使用C撤消Exception完成此CompletableFuture。尚未完成的依赖CompletableFutures也将异常完成,并使用由此引起的CompletionException

[...]

参数:

MayInterruptFrunning-此值在此实现中无效,因为中断不用于控制处理。

CompletableFuture对象与任何可能对它们有可访问引用的线程完全无关。换句话说,这些对象并不意味着给线程发信号。这种类型的未来基本上是带有注册侦听器选项的结果的持有者。

whenXyzthenAbc的所有行为都在CompletableFuture对象中注册。该行为何时执行取决于很多事情:哪个线程将来完成(成功或例外),是否使用*Async方法注册了continuations,等等。这在javadoc中有详细说明。

例如,创建一个CompletableFuture,并将其交给一些线程。据推测,其中一个线程将完成它。这对其他线程没有影响。他们仍在继续做他们正在做或试图做的事情。

public static void main(String[] args) throws Exception {
    CompletableFuture<String> promise = new CompletableFuture<>();
    ExecutorService executorService = Executors.newFixedThreadPool(3);
    Runnable action = () -> {
        if (promise.complete("done")) {
            System.out.println("completed by " + Thread.currentThread());
        } else {
            System.out.println("somebody got there first");
        }
    };
    executorService.submit(action);
    executorService.submit(action);
    executorService.submit(action);

    executorService.shutdown();
    executorService.awaitTermination(100, TimeUnit.MILLISECONDS);
    System.out.println(promise.get());
}

 类似资料:
  • 问题内容: 我有一个名为的方法的对象,该方法启动三个线程。 每个线程执行完毕后,如何获得通知? 有没有办法知道一个(或全部)线程是否已完成或仍在执行? 问题答案: 你可以通过多种方式执行此操作: 在主线程中使用以阻塞方式等待每个线程完成,或者 以轮询方式(通常不鼓励使用)检查,等待每个线程完成,或者 非常规的,对于每个有问题的线程,调用来调用对象中的方法,并对每个线程进行编程以在完成时抛出未捕获的

  • 我试着看过类似的,但没有一个解决方案奏效。我以前运行的应用程序没有问题,但我的新应用程序突然开始给我带来问题。当我尝试运行它时,它总是失败: 控制台显示的内容如下:

  • 当我在PyCharm中手动停止脚本时,进程以退出代码137结束。但是我没有停止剧本。还有出口代码137。有什么问题? Python版本是3.6,在运行xgboost.train()方法时进程完成。

  • 我有一个简单的服务任务,它将变量“foo”设置为“bar”。当一个流程只包含一个任务,并且我使用“运行时/Process-Instances”启动它时,我可以在响应中看到变量“foo”。当我在服务任务之前添加一个用户任务,并使用action:complete on“runtime/tasks”完成任务时,我只得到一个200的结果代码。如何获得结果变量?

  • 我不知道如何获取消息的消息链接,discordjs文档似乎没有任何关于消息链接的内容。我试过这个: 但其结果是“行会没有定义”。我这样做对吗?

  • 我正在学习Java 1.8中的CompletableFuture,在理解所有代码时遇到了困难。主线程似乎不会等待任何可完成的未来完成。 看见https://github.com/nurkiewicz/reactive/blob/master/src/test/java/be/more/reactive/S03_AllOf.java例如,我正在测试。 测试作业在打印任何结果之前完成。 有两种(丑陋的