我正在运行CompletableFuture
的两个示例,它们等待1秒并向控制台打印一些内容。第一个示例在0.5秒后被中断。所以我希望只有第二个示例打印,但实际上两个示例都打印了。这是怎么回事?
代码如下:
CompletableFuture<Void> c1 = CompletableFuture.runAsync(() -> {
System.out.println("Start CF 1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(1);
});
CompletableFuture<Void> c2 = CompletableFuture.runAsync(() -> {
System.out.println("Start CF 2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(2);
});
long start = System.currentTimeMillis();
try {
c1.get(500, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
System.out.println("CF interrupted after " + (System.currentTimeMillis() - start) + "ms");
}
c2.get();
它会打印:
Start CF 1
Start CF 2
CF interrupted after 510ms
2
1
2条答案
按热度按时间jjhzyzn01#
你为什么认为应该这样做呢?如果两个消费者都想处理同一个未来的结果,而其中一个准备比另一个等待更长的时间呢?第一个会杀死它,因为第二个可能已经及时完成了。
在任何情况下,Java都没有杀死任务的概念。你能做的最好的事情是设置一个标志,要求它停止--一个中断--但是这依赖于任务检查和遵守这个标志。你的任务是这样做的,因为
Thread.sleep()
隐式地检查中断标志,但是这是一个人为的例子,很多任务从来不会检查它。gorkyyrv2#
get
方法的逾时只会告知何时应该停止执行get
方法。它不会影响结果的计算。这适用于所有future。因此,要中断一个任务,需要调用
cancel(true)
,但在CompletableFuture
的情况下,即使这样也不会中断任务:参数:
mayInterruptIfRunning
-此值在此实现中不起作用,因为中断不用于控制处理。如果你想要可中断的任务,你需要使用
ExecutorService
,但是你也可以使用与CompletableFuture
的默认执行器相同的线程池:请注意,中断可能仍然太慢,无法阻止打印
1
。在我的机器上,我至少需要Thread.sleep(1100);
才能在打印之前中断任务。