[英]How to interrupt CompletableFuture::join?
I've found that CompletableFuture::join
seems uninterruptible when not completed: 我发现CompletableFuture::join
在未完成时似乎是不可中断的 :
// CompletableFuture::join implementation from JDK 8 sources
public T join() {
Object r;
return reportJoin((r = result) == null ? waitingGet(false) : r);
}
In above implementation, waitingGet(false)
will ignore the interrupt flag of the working Thread
and continue waiting. 在上面的实现中, waitingGet(false)
将忽略工作Thread
的中断标志并继续等待。 I'm wondering how can I interrupt a Thread
in which I call CompletableFuture::join
. 我想知道如何中断我称之为CompletableFuture::join
的Thread
。
Do not use join()
if you want to support interruption, use get()
instead. 如果要支持中断,请不要使用join()
,而是使用get()
。 Basically they are the same except: 基本上它们是相同的,除了:
join()
is only defined in CompletableFuture
whereas get()
comes form interface Future
join()
仅在CompletableFuture
定义,而get()
来自表单接口Future
join()
wraps exceptions in CompletionException
whereas get()
wraps them in ExecutionException
join()
在CompletionException
包装异常,而get()
在ExecutionException
包装它们 get()
might be interrupted and would then throw an InterruptedException
get()
可能会被中断,然后会抛出InterruptedException
Note that what you interrupt is the Thread
, not the Future
. 请注意,您打断的是Thread
,而不是Future
。 For example, the following code interrupts the main thread while it is waiting on myFuture.get()
: 例如,以下代码在等待myFuture.get()
时中断主线程:
CompletableFuture<Void> myFuture = new CompletableFuture<>();
Thread mainThread = Thread.currentThread();
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1000);
System.out.println("Interrupting…");
mainThread.interrupt();
Thread.sleep(1000);
System.out.println("Completing");
myFuture.complete(null);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
try {
myFuture.get();
System.out.println("Get succeeded");
} catch (Exception e) {
System.out.println("Get failed");
e.printStackTrace();
}
Output: 输出:
Interrupting…
Get failed
java.lang.InterruptedException
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:347)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at CompletableFutureInteruption.main(CompletableFutureInteruption.java:37)
…
If you replace get()
by join()
, the interrupt will indeed not work. 如果用join()
替换get()
,则中断确实不起作用。
I finally give up to interrupt the Thread which blocks in waiting for CompletableFuture::join
finish. 我终于放弃了在等待CompletableFuture::join
完成时阻塞的Thread。
Instead I use CompletableFuture::allof
to get a CompletableFuture
all which ends when all my joined Futures end. 相反,我使用CompletableFuture::allof
来获得CompletableFuture
所有这些都在我所有加入的期货结束时结束。 And then just call the get()
method of the all Future in the working thread. 然后在工作线程中调用所有 Future的get()
方法。 When get()
returns, I then collect all my results by iterating all my joined Futures and call getNow
on them. 当get()
返回时,我会通过迭代所有已加入的Futures并在其上调用getNow
来收集我的所有结果。 Such a procedure is interruptible. 这样的程序是可以中断的。
I clearly known in the end you are not actually looking for the interruptible , but as a way around it can be interrupted by exceptions as follows (though it's join()
): 我最后清楚地知道你实际上并不是在寻找可中断的 ,但是作为一种解决方法可能会被例外中断,如下所示(尽管它是join()
):
private static void testCompleteExceptionally() {
String name = "Hearen";
CompletableFuture<String> completableFuture
= CompletableFuture.supplyAsync(() -> {
delay(500L);
if (name == null) {
throw new RuntimeException("Computation error!");
}
return "Hello, " + name;
});
if (name != null) {
completableFuture.completeExceptionally(new RuntimeException("Calculation failed!"));
}
out.println(completableFuture.handle((s, t) -> s != null ? s : "Hello, Stranger!" + t.toString()).join());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.