How to interrupt CompletableFuture :: join?
I found CompletableFuture :: join seems to be intact if not complete:
// CompletableFuture::join implementation from JDK 8 sources
public T join() {
Object r;
return reportJoin((r = result) == null ? waitingGet(false) : r);
}
The above implementation waitingGet(false)
will ignore the worker thread interrupt flag and continue waiting. I am wondering how I can interrupt the Thread in which I call CompletableFuture :: join.
source to share
Don't use join()
if you want to support interrupt, use get()
. They are basically the same except:
-
join()
comes from the interfaceCompletionStage
whereas theget()
interface form appearsFuture
-
join()
excludes exceptions fromCompletionException
, whereasget()
wraps them inExecutionException
-
get()
can be interrupted and then discardedInterruptedException
Note that what you are interrupting is Thread
, not Future
. For example, the following code interrupts the main thread while it is waiting for 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()
with join()
, the interrupt really won't work.
source to share
I will finally give up on interrupting a Thread that blocks pending completion CompletableFuture::join
.
Instead, I use CompletableFuture::allof
to get CompletableFuture
everything that ends when all of my attached futures expire. And then just call the method get()
for the whole Future on the worker thread. When it get()
returns, I then collect all my results by iterating over all of my associated futures and calling getNow
on them. This procedure is interrupted.
source to share