Do not use join()
if you want to support interruption, use get()
instead. Basically they are the same except:
join()
is only defined in CompletableFuture
whereas get()
comes form interface Future
join()
wraps exceptions in CompletionException
whereas get()
wraps them in ExecutionException
get()
might be interrupted and would then throw an InterruptedException
Note that what you interrupt is the Thread
, not the Future
. For example, the following code interrupts the main thread while it is waiting on 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.
CompletableFuture::cancel
won't interrupt the thread. What I want to do is to interrupt a thread which blocks in aCompletableFuture::join
operation. Maybe I should describe my question more clearly. – Repro