CompletableFuture 在工作线程进入睡眠状态后没有响应
CompletableFuture not responding after worker thread send to sleep
我正在尝试了解 ConsumableFuture。
基本上,我向 ConsumableFuture 提供一个任务,然后让工作线程 运行 该任务休眠 2 秒。我希望工作线程在 2 秒后恢复执行并 return 结果。
public class CompletableFutureDemo {
public static void main(String[] args) {
System.err.println("Application started");
CompletableFuture
.supplyAsync(()->work1())
.thenAccept(op-> System.out.println(op));
System.err.println("Application ended");
}
public static int work1() {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("work1 called");
return (int) (Math.random() * 100);
}
}
输出:
Application started
ForkJoinPool.commonPool-worker-1
Application ended
为什么工作线程没有恢复?
但是如果我从工作线程中删除 sleep 语句,我就会得到所需的输出。
Application started
ForkJoinPool.commonPool-worker-1
work1 called
Application ended
64
正如@Slaw 已经在评论中指出的那样,主线程在工作线程休眠时完成并退出应用程序,因此您可以调用join让主线程等待直到工作线程完成
System.err.println("Application started");
CompletableFuture
.supplyAsync(()->work1())
.thenAccept(op-> System.out.println(op)).join();
System.err.println("Application ended");
输出:
ForkJoinPool.commonPool-worker-3
Application started
work1 called
12
Application ended
或者你可以让主线程在它工作完成后等待
System.err.println("Application started");
CompletableFuture<Void> completableFuture = CompletableFuture
.supplyAsync(()->work1())
.thenAccept(op-> System.out.println(op));
System.err.println("Application ended");
completableFuture.join();
输出:
ForkJoinPool.commonPool-worker-3
Application started
Application ended
work1 called
25
如果您有多个 CompletableFuture 对象,那么您可以使用 allOf
等待所有任务完成(但在后台每个可完成的任务将异步执行)
CompletableFuture.allOf(completableFuture1,completableFuture1).join();
我通过提供自己的 Executor 实例实现了异步操作并避免将其标记为守护进程。 (任何类型的执行器)
CompletableFuture
.supplyAsync(()->work1(), Executors.newFixedThreadPool(2))
.thenAccept(op-> System.out.println(op));
我认为这可以避免创建守护线程,类似于我们在 ExecutorServices 中的线程。
感谢@Slaw 提供有关守护线程的信息。我想了解更多为什么 ForkJoin 架构会默认将线程标记为守护进程。
我正在尝试了解 ConsumableFuture。 基本上,我向 ConsumableFuture 提供一个任务,然后让工作线程 运行 该任务休眠 2 秒。我希望工作线程在 2 秒后恢复执行并 return 结果。
public class CompletableFutureDemo {
public static void main(String[] args) {
System.err.println("Application started");
CompletableFuture
.supplyAsync(()->work1())
.thenAccept(op-> System.out.println(op));
System.err.println("Application ended");
}
public static int work1() {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("work1 called");
return (int) (Math.random() * 100);
}
}
输出:
Application started
ForkJoinPool.commonPool-worker-1
Application ended
为什么工作线程没有恢复?
但是如果我从工作线程中删除 sleep 语句,我就会得到所需的输出。
Application started
ForkJoinPool.commonPool-worker-1
work1 called
Application ended
64
正如@Slaw 已经在评论中指出的那样,主线程在工作线程休眠时完成并退出应用程序,因此您可以调用join让主线程等待直到工作线程完成
System.err.println("Application started");
CompletableFuture
.supplyAsync(()->work1())
.thenAccept(op-> System.out.println(op)).join();
System.err.println("Application ended");
输出:
ForkJoinPool.commonPool-worker-3
Application started
work1 called
12
Application ended
或者你可以让主线程在它工作完成后等待
System.err.println("Application started");
CompletableFuture<Void> completableFuture = CompletableFuture
.supplyAsync(()->work1())
.thenAccept(op-> System.out.println(op));
System.err.println("Application ended");
completableFuture.join();
输出:
ForkJoinPool.commonPool-worker-3
Application started
Application ended
work1 called
25
如果您有多个 CompletableFuture 对象,那么您可以使用 allOf
等待所有任务完成(但在后台每个可完成的任务将异步执行)
CompletableFuture.allOf(completableFuture1,completableFuture1).join();
我通过提供自己的 Executor 实例实现了异步操作并避免将其标记为守护进程。 (任何类型的执行器)
CompletableFuture
.supplyAsync(()->work1(), Executors.newFixedThreadPool(2))
.thenAccept(op-> System.out.println(op));
我认为这可以避免创建守护线程,类似于我们在 ExecutorServices 中的线程。
感谢@Slaw 提供有关守护线程的信息。我想了解更多为什么 ForkJoin 架构会默认将线程标记为守护进程。