[英]CompletableFuture.get not waiting for final block
我有一个自定义的 ExecutorService,
class CustomExecutorService implements ExecutorService {
ExecutorService delegate;
public CustomExecutorService(ExecutorService delegate){
this.delegate = delegate;
}
// All methods are just delegated to the delegate except execute
public void execute(Runnable command) {
this.delegate.execute(wrapRunnable(command));
}
private Runnable wrapRunnable(final Runnable command) {
return () -> {
try {
command.run();
} finally {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Finalizer done.");
}
};
}
}
现在这是我的测试代码,
ExecutorService executorService = new CustomExecutorService(Executors.newCachedThreadPool());
CompletableFuture.runAsync(() -> System.out.println("Command done."), executorService).get();
System.out.println("Main Thread Done.");
现在我希望发生以下输出,
Command done.
Finalizer done. //After a wait of 2 seconds
Main Thread Done.
然而正在发生的事情是,
Command done.
Main Thread Done.
它甚至没有等待finally
块并且主线程正在退出。 我无法解释这种行为,因为CompletableFuture#get
应该是阻塞的,但它似乎没有等待finallly
阻塞。
据我所知, finally
不能保证,如果要执行finally
是要由守护线程和所有其他非守护线程退出前执行finally
被调用。 然而 ExecutorService 线程是非守护线程,所以finally
应该被执行。
我在corretto-11.0.11
上运行这个
当您运行CompletableFuture.runAsync
它将您的Runnable
包装在一个运行 runnable 的任务(源代码中的AsyncRun
)中,然后将 CompletableFuture 标记为完成。 这是传递给执行者的内容。
在您的执行程序中,您正在包装该任务,因此在您的finally
块运行时,未来已被标记为完成,这就是get()
在该点之后立即返回的原因。
查看CompletableFuture
1627行(Jdk 1.8)的源码如下:
public void run() {
CompletableFuture<Void> d; Runnable f;
if ((d = dep) != null && (f = fn) != null) {
dep = null; fn = null;
if (d.result == null) {
try {
f.run();
d.completeNull(); // line 1627
} catch (Throwable ex) {
d.completeThrowable(ex);
}
}
d.postComplete();
}
}
}
当Runnable f
完成后, CompletableFuture 的结果将被设置为null
,然后get()
方法将不再被阻塞。 在你的情况下Runnable f
等于System.out.println("Command done.")
可以在CompletableFuture runAsync(Runnable runnable, Executor executor)
的入口处设置断点,一CompletableFuture runAsync(Runnable runnable, Executor executor)
调试,你会发现什么时候设置了 CompletableFuture 的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.