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.

+3


source to share


2 answers


Don't use join()

if you want to support interrupt, use get()

. They are basically the same except:

  • join()

    comes from the interface CompletionStage

    whereas the get()

    interface form appearsFuture

  • join()

    excludes exceptions from CompletionException

    , whereas get()

    wraps them inExecutionException

  • get()

    can be interrupted and then discarded InterruptedException

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:

InterruptingGet 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.

+5


source


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.

+2


source







All Articles