这两种方法之间的区别
Difference between these 2 methods
我无法发现为什么这两种方法的行为不同。两者之间的唯一区别是睡眠方法调用。
在第一种方法中,我期望第二次未来执行将等待第一个未来完成,因为它取决于第一个未来的结果。
请帮助我理解为什么这两种方法的行为不同,或者我的代码中是否存在逻辑错误?
我已经在调试模式下尝试 运行,但结果仍然相同。
public static void thenComposeWithSleep() {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return "Hello";
}).thenCompose(value -> CompletableFuture.supplyAsync(() -> value + " Then compose is been called"));
completableFuture.thenAccept(System.out::println);
}
public static void thenCompose() {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello")
.thenCompose(value -> CompletableFuture.supplyAsync(() -> value + " Then compose is been called"));
completableFuture.thenAccept(System.out::println);
}
第一种方法的预期输出:"Hello Then compose is been called"。
第一种方法的实际输出:空字符串
第二种方法的预期和实际输出相同。
输出:"Hello Then compose is been called"
这里的问题是
CompletableFuture.supplyAsync()
将执行权交给
ForkJoinPool.commonPool()
当它以守护进程模式运行时(根据 Java7 文档,这是默认模式),如果您的主线程终止,所有未完成的异步任务将被丢弃并且永远不会完成。
所以我猜你假设 "Empty String" 实际上是
System.out::println
根本没有执行。
为 class
说明这一点
public class DaemonsAtPlay {
public static void thenComposeWithSleep() {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return "Slept"; //HERE
}).thenCompose(value -> CompletableFuture.supplyAsync(() -> value + " Then compose is been called"));
completableFuture.thenAccept(DaemonsAtPlay::report); //HERE
}
public static void thenCompose() {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello")
.thenCompose(value -> CompletableFuture.supplyAsync(() -> value + " Then compose is been called"));
completableFuture.thenAccept(DaemonsAtPlay::report); //HERE
}
private static final AtomicInteger counter = new AtomicInteger();
static void report(String msg) {
System.out.println("report: " + counter.incrementAndGet() + "; message: >" + msg + "<");
}
public static void executeMultiple(int iterations, boolean withsleep) {
for(int i=0; i<iterations; ++i) {
if(withsleep) {
thenComposeWithSleep();
} else {
thenCompose();
}
}
}
public static void main(String... none) throws Exception {
executeMultiple(100, false);
executeMultiple(100, true);
report("exiting main");
}
}
我得到了输出
report: 1; message: >Hello Then compose is been called<
report: 2; message: >Hello Then compose is been called<
report: 3; message: >Hello Then compose is been called<
report: 4; message: >Hello Then compose is been called<
report: 5; message: >Hello Then compose is been called<
report: 6; message: >Hello Then compose is been called<
report: 7; message: >Hello Then compose is been called<
report: 8; message: >Hello Then compose is been called<
report: 9; message: >Hello Then compose is been called<
report: 10; message: >Hello Then compose is been called<
report: 11; message: >Hello Then compose is been called<
report: 12; message: >Hello Then compose is been called<
report: 13; message: >Hello Then compose is been called<
report: 14; message: >Hello Then compose is been called<
report: 15; message: >Hello Then compose is been called<
report: 16; message: >Hello Then compose is been called<
report: 17; message: >Hello Then compose is been called<
report: 18; message: >Hello Then compose is been called<
report: 19; message: >Hello Then compose is been called<
report: 20; message: >Hello Then compose is been called<
report: 21; message: >Hello Then compose is been called<
report: 22; message: >exiting main<
这说明不仅 'slept' 任务而且许多 'unslept' 任务都没有终止。
如果您想等待所有 CompletableFuture 任务终止,您可以使用
CompletableFuture.join()
在主线程上。
我无法发现为什么这两种方法的行为不同。两者之间的唯一区别是睡眠方法调用。
在第一种方法中,我期望第二次未来执行将等待第一个未来完成,因为它取决于第一个未来的结果。
请帮助我理解为什么这两种方法的行为不同,或者我的代码中是否存在逻辑错误?
我已经在调试模式下尝试 运行,但结果仍然相同。
public static void thenComposeWithSleep() {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return "Hello";
}).thenCompose(value -> CompletableFuture.supplyAsync(() -> value + " Then compose is been called"));
completableFuture.thenAccept(System.out::println);
}
public static void thenCompose() {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello")
.thenCompose(value -> CompletableFuture.supplyAsync(() -> value + " Then compose is been called"));
completableFuture.thenAccept(System.out::println);
}
第一种方法的预期输出:"Hello Then compose is been called"。
第一种方法的实际输出:空字符串
第二种方法的预期和实际输出相同。
输出:"Hello Then compose is been called"
这里的问题是
CompletableFuture.supplyAsync()
将执行权交给
ForkJoinPool.commonPool()
当它以守护进程模式运行时(根据 Java7 文档,这是默认模式),如果您的主线程终止,所有未完成的异步任务将被丢弃并且永远不会完成。
所以我猜你假设 "Empty String" 实际上是
System.out::println
根本没有执行。
为 class
说明这一点public class DaemonsAtPlay {
public static void thenComposeWithSleep() {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return "Slept"; //HERE
}).thenCompose(value -> CompletableFuture.supplyAsync(() -> value + " Then compose is been called"));
completableFuture.thenAccept(DaemonsAtPlay::report); //HERE
}
public static void thenCompose() {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello")
.thenCompose(value -> CompletableFuture.supplyAsync(() -> value + " Then compose is been called"));
completableFuture.thenAccept(DaemonsAtPlay::report); //HERE
}
private static final AtomicInteger counter = new AtomicInteger();
static void report(String msg) {
System.out.println("report: " + counter.incrementAndGet() + "; message: >" + msg + "<");
}
public static void executeMultiple(int iterations, boolean withsleep) {
for(int i=0; i<iterations; ++i) {
if(withsleep) {
thenComposeWithSleep();
} else {
thenCompose();
}
}
}
public static void main(String... none) throws Exception {
executeMultiple(100, false);
executeMultiple(100, true);
report("exiting main");
}
}
我得到了输出
report: 1; message: >Hello Then compose is been called<
report: 2; message: >Hello Then compose is been called<
report: 3; message: >Hello Then compose is been called<
report: 4; message: >Hello Then compose is been called<
report: 5; message: >Hello Then compose is been called<
report: 6; message: >Hello Then compose is been called<
report: 7; message: >Hello Then compose is been called<
report: 8; message: >Hello Then compose is been called<
report: 9; message: >Hello Then compose is been called<
report: 10; message: >Hello Then compose is been called<
report: 11; message: >Hello Then compose is been called<
report: 12; message: >Hello Then compose is been called<
report: 13; message: >Hello Then compose is been called<
report: 14; message: >Hello Then compose is been called<
report: 15; message: >Hello Then compose is been called<
report: 16; message: >Hello Then compose is been called<
report: 17; message: >Hello Then compose is been called<
report: 18; message: >Hello Then compose is been called<
report: 19; message: >Hello Then compose is been called<
report: 20; message: >Hello Then compose is been called<
report: 21; message: >Hello Then compose is been called<
report: 22; message: >exiting main<
这说明不仅 'slept' 任务而且许多 'unslept' 任务都没有终止。
如果您想等待所有 CompletableFuture 任务终止,您可以使用
CompletableFuture.join()
在主线程上。