Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.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
Java 是否始终执行CompletableFuture回调_Java_Completable Future - Fatal编程技术网

Java 是否始终执行CompletableFuture回调

Java 是否始终执行CompletableFuture回调,java,completable-future,Java,Completable Future,我有两个服务电话: String call1() { ... return "ok"; } void call2(String) { ... } 我知道用回调实现CompletableFuture的基本方法如下 CompletableFuture<Void> future = CompletableFuture .supplyAsync(() -> call1()) .thenAccept(s -> call2(s)); future.join(); Completa

我有两个服务电话:

String call1() { ... return "ok"; }
void call2(String) { ... }
我知道用回调实现CompletableFuture的基本方法如下

CompletableFuture<Void> future = CompletableFuture
.supplyAsync(() -> call1())
.thenAccept(s -> call2(s));
future.join();
CompletableFuture=CompletableFuture
.SupplySync(()->call1())
。然后接受->呼叫2;
future.join();
如果我将两个链接的CompletableFutures分开,比如:

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> call1());
CompletableFuture<Void> future2 = future1.thenAccept(s -> call2(s));
future1.join(); // will call2 be executed at this time?
CompletableFuture-future1=CompletableFuture.supplyAsync(()->call1());
CompletableFuture2=future1。然后接受->调用2;
future1.join();//此时是否将执行call2?
这与在future2上调用join()有什么不同:

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> call1());
CompletableFuture<Void> future2 = future1.thenAccept(s -> call2(s));
future2.join();
CompletableFuture-future1=CompletableFuture.supplyAsync(()->call1());
CompletableFuture2=future1。然后接受->调用2;
未来2.加入();
如果我对这两个函数都调用join(),会怎么样

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> call1());
CompletableFuture<Void> future2 = future1.thenAccept(s -> call2(s));
future1.join();
future2.join();
CompletableFuture-future1=CompletableFuture.supplyAsync(()->call1());
CompletableFuture2=future1。然后接受->调用2;
未来1.加入();
未来2.加入();
从运行我的示例代码来看,它们似乎都是一样的。但我觉得某处可能出了问题。谢谢

它们不一样

简而言之,您可以将其视为
future1
future2
保存不同任务的结果(即使
future2
使用了
future1
的结果,它也是一个不同的未来)

future1.join()
将一直阻止,直到
()->call1()
结束,
future2
的任务在此之前不会启动
future2.join()
将等待
s->call2
完成

如果我将两个链接的CompletableFutures分开,比如:

就任务执行而言,这没有什么区别。这要么是风格的问题,要么只在需要单独使用两个未来对象时才重要

如果我对这两个函数都调用join(),会怎么样

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> call1());
CompletableFuture<Void> future2 = future1.thenAccept(s -> call2(s));
future1.join();
future2.join();
在这种情况下,调用
future1.join()
是多余的,因为在这两个
调用之间没有做任何事情。如果您想在“任务1完成后和任务2完成前”执行某些操作,这是有意义的。

在这种情况下,调用
future2.join()
就足够了


下面的代码段应显示其行为:

public static void main(String[] args) {
    CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> delay());
    CompletableFuture<Void> future2 = future1.thenRun(() -> delay());

    long start = System.currentTimeMillis();

    future1.join();
    System.out.println("Future 1 done. Waiting for future 2: " 
            + (System.currentTimeMillis() - start));

    future2.join();
    System.out.println("Future 2 complete: " 
            + (System.currentTimeMillis() - start));
}

static void delay() {
    try {
        TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
但是当您删除
future1.join()
时,输出变成:

Future 2 complete: 10001

这仅仅意味着
future1.join()
是多余的,除非您在两个future1.join()的完成之间有操作要执行,
supplyAsync
然后accept
方法应该根据文档在单独的线程上自动执行:

所有没有显式执行器参数的异步方法都使用ForkJoinPool.commonPool()执行

在您的示例中,唯一的区别是,由于加入,线程在继续之前等待不同的事件。以下是分项数字:

CompletableFuture<Void> future = CompletableFuture
.supplyAsync(() -> call1())
.thenAccept(s -> call2(s));
future.join();
这将只等待
call1
完成并继续<代码>调用2
仍将执行

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> call1());
CompletableFuture<Void> future2 = future1.thenAccept(s -> call2(s));
future2.join();
CompletableFuture-future1=CompletableFuture.supplyAsync(()->call1());
CompletableFuture2=future1。然后接受->调用2;
未来2.加入();
这与第一个相同

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> call1());
CompletableFuture<Void> future2 = future1.thenAccept(s -> call2(s));
future1.join();
future2.join();
CompletableFuture-future1=CompletableFuture.supplyAsync(()->call1());
CompletableFuture2=future1。然后接受->调用2;
未来1.加入();
未来2.加入();

调用
future1.join()
call1
完成时结束,然后
future2.join()
call2
完成时结束。这在功能上也应该与第一个相同。

谢谢。如果第二个未来是异步的,那么所有这些仍然有效吗?i、 e.CompletableFuture2=future1.thenRunAsync(()->delay());在你的代码里?那么我认为调用future2.join()将在主线程上阻塞,并失去在异步上调用future2的意图?但是调用future1.join()可以保证future2将被执行吗?谢谢。那么,如果将thenAccept()更改为ThenAcceptSync(),该怎么办?我想这只会将call2()放在第三个线程上,但所有其他参数仍然有效?是的,这是对的,但是如果需要并行执行多个任务,通常您希望调用
thenaccessync()
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> call1());
CompletableFuture<Void> future2 = future1.thenAccept(s -> call2(s));
future1.join();
future2.join();