Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何从与CompletableFutures关联的线程中发出已完成或已取消的信号?_Multithreading_Java 8_Java.util.concurrent_Completable Future - Fatal编程技术网

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

Multithreading 如何从与CompletableFutures关联的线程中发出已完成或已取消的信号?,multithreading,java-8,java.util.concurrent,completable-future,Multithreading,Java 8,Java.util.concurrent,Completable Future,我读了很多关于CompletableFutures的书,他们关注的是一个事实,即CompletableFutures和Future一样,无法访问底层的计算代码。那么,如何从与completableFuture关联的任何任务中发出complete()或cancel()信号(或者检查isCancelled(),如果您想从外部中断计算) 编辑:让我感到困惑的一件事是,CF的可组合性或手动可设置性都超过了其他选项,在我看来,如果实现的话,这两个选项是非常正交的,如: CompletableFuture.

我读了很多关于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的接口作为输入一样,但不知道如何使用。类似于
Function
而不是Callables/Runnables,因此我们可以将其用作:

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是否仍然是一种半方便的设计?

看看javadoc:

如果尚未完成,则设置
get()
和相关 方法设置为给定值

如果尚未完成,则使用
取消异常
。依赖的
CompletableFuture
s未完成的 已完成的也将例外完成,包括
CompletionException
由此
CancellationException
引起

[……]

参数:

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

CompletableFuture
对象与任何可能具有可访问引用的线程完全无关。换句话说,这些对象不是用来给线程发信号的。这种类型的未来基本上是结果的持有者,可以选择注册监听器

whenXyz
thenAbc
的所有行为都注册到
CompletableFuture
对象中。该行为何时执行取决于许多因素:未来哪个线程完成(成功或异常),是否使用
*Async
方法注册continuations,等等。这在中进行了说明


例如,创建一个
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());
}
publicstaticvoidmain(字符串[]args)引发异常{
CompletableFuture promise=新的CompletableFuture();
ExecutorService ExecutorService=Executors.newFixedThreadPool(3);
可运行操作=()->{
如果(承诺完成(“完成”)){
System.out.println(“由”+Thread.currentThread()完成);
}否则{
System.out.println(“某人首先到达那里”);
}
};
执行服务。提交(操作);
执行服务。提交(操作);
执行服务。提交(操作);
executorService.shutdown();
执行器服务。等待终止(100,时间单位。毫秒);
System.out.println(promise.get());
}

1)哇,考虑到referer代码将在一个单独的线程中执行,我没有假设您可以像那样在主线程中引用promise var。2) 我读过的其他每一个例子都通过supply/runAsync使用CompletableFutures,在可调用代码的实例化过程中,您如何引用其自身的承诺?。3) 如果不使用lambdas,是否需要将可调用/可运行任务的CF-in构造函数作为每个线程的简单信号传递?那么,它有什么了不起的地方,人们说它是Scala的未来之路呢?通过
SupplySync
runAsync
,你可以获得一个
完整的未来。它不一定已经完成了。您仍然可以将它交给另一个线程,并让该线程完成它。你可以用任何合适的方式传递未来:构造函数参数、局部变量捕获等等。我不知道你所说的简单信号量是什么意思。我相信Scala有
future
Promise
。Java的
CompletableFuture
是两者的组合。@whimmusical:如果只使用
runAsync
supplyAsync
,在
ExecutorService
上调用
submit
,获得
Future
,没有区别。因此,
CompletableFuture
Future
之间的主要区别已经通过它的名称给出了,您可以显式地完成它,如本答案所示。这是否与“Scala的做法”有关,我不知道(也不在乎)。它对某些任务很有用,但我不会重写所有与并发相关的代码,现在使用
CompletableFuture