gpt4 book ai didi

java - CompletableFuture 的执行顺序

转载 作者:行者123 更新时间:2023-12-02 01:41:01 34 4
gpt4 key购买 nike

我试图理解 java 中 completableFutures 的非阻塞回调性质

 CompletableFuture.supplyAsync(() -> {
try {
//Thread.sleep(20000);
System.out.println("supplyAsync Thread name " + Thread.currentThread().getName());
return "str";

} catch (Exception e) {
return "";
}


}).thenApply(str -> {
System.out.println("thenApply Thread name " + Thread.currentThread().getName());
return str;
}).thenApply(str1 -> {
System.out.println("thenApply Thread name " + Thread.currentThread().getName());
return str1;
}).thenAccept(str3 -> {
System.out.println("thenAccept Thread name " + Thread.currentThread().getName());
});
System.out.println("Thread name " + Thread.currentThread().getName());

使用上面的代码我总是看到如下所示的结果

supplyAsync 线程名称 ForkJoinPool.commonPool-worker-1
然后应用线程名称main
然后应用线程名称main
thenAccept 线程名称 main
线程名称 main

这个顺序似乎表明主线程等待直到所有 Futures 线程执行。这不就是被屏蔽的表现吗。
我尝试将 Thread.sleep 添加到 SupplyAsync 方法,输出为

线程名称 main

futures 线程中的打印语句似乎都没有被执行。我对非阻塞的理解是能够打印

线程名称 mainSupplyAsync 线程名称
ForkJoinPool.commonPool-worker-1
然后应用线程名称main
然后应用线程名称main
thenAccept 线程名称 main

如果在Javascript中执行类似的代码,则可能会出现上述控制台输出

上面的内容在 Java 中可行吗?

最佳答案

不,它没有阻塞。默认情况下,Completable future 在 ForkJoinPool.commonPool 上执行其任务,其中公共(public)池的线程是守护进程线程。当主线程完成执行时,JVM 将终止池中的所有其他守护线程,这就是为什么在第二种情况下您只能看到线程名称主要.

但是,您可以将自己的执行者传递给完整的 future 。

CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
System.out.println("supplyAsync Thread name " + Thread.currentThread().getName());
System.out.println("Is daemon Thread: " + Thread.currentThread().isDaemon());
return "str";

} catch (Exception e) {
return "";
}

}, Executors.newFixedThreadPool(4)).thenApply(str -> {
System.out.println("thenApply Thread name " + Thread.currentThread().getName());
return str;
}).thenApply(str1 -> {
System.out.println("thenApply Thread name " + Thread.currentThread().getName());
return str1;
}).thenAccept(str3 -> {
System.out.println("thenAccept Thread name " + Thread.currentThread().getName());
});
System.out.println("Thread name " + Thread.currentThread().getName());

如果运行上面的代码,您可以获得如下输出:

Thread name main
supplyAsync Thread name pool-1-thread-1
Is daemon Thread: false
thenApply Thread name1 pool-1-thread-1
thenApply Thread name1 pool-1-thread-1
thenAccept Thread name1 pool-1-thread-1

关于java - CompletableFuture 的执行顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57489129/

34 4 0