Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JDK8 CompletableFuture.supplyAsync how to deal with interruptedException

CompletableFuture.supplyAsync(
() -> {
    transporter.write(req);
    //here take the value from a blocking queue,will throw a interruptedException
    return responseQueue.take();
},  executorService);

The common method to deal with interruptedException is either to interrupt again or direct throw interruptedException, but both cannot work. Anyone have the idea?

like image 517
GrapeBaBa Avatar asked Apr 20 '14 16:04

GrapeBaBa


People also ask

How do you handle interruptedException in CompletableFuture?

The common method to deal with interruptedException is either to interrupt again or direct throw interruptedException, but both cannot work.

How do you handle Completable futures?

CompletableFuture provides three methods to handle them: handle() , whenComplete() , and exceptionally() . They look quite similar and it's easy to get lost when you are not familiar with the API.

What does CompletableFuture supplyAsync do?

supplyAsync. Returns a new CompletableFuture that is asynchronously completed by a task running in the given executor with the value obtained by calling the given Supplier.

What is difference between supplyAsync and runAsync?

The difference between runAsync() and supplyAsync() is that the former returns a Void while supplyAsync() returns a value obtained by the Supplier. Both methods also support a second input argument — a custom Executor to submit tasks to.


Video Answer


3 Answers

I change the code like this.

    CompletableFuture<Rep> result = new CompletableFuture<>();
    CompletableFuture.runAsync(() -> {

        transporter.write(req);
        try {
            Rep rep = responseQueue.take();
            result.complete(rep);
        } catch (InterruptedException e) {
            result.completeExceptionally(e);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            result.completeExceptionally(e);
        }

    }, executorService);
    return result;
like image 170
GrapeBaBa Avatar answered Oct 12 '22 23:10

GrapeBaBa


I ran into the same question, but after reading more from comments here and reference book I think you can do either one of these two:

1 (what I end up doing):

CompletableFuture.runAsync(() -> {
    transporter.write(req);
    try {
        Rep rep = responseQueue.take();
        result.complete(rep);
    } catch (Exception e) {
        throw new CompletionException(e);
    }
}, executorService);
return result;

or 2:

CompletableFuture<Rep> result = new CompletableFuture<>();
new Thread(()-> {
    transporter.write(req);
    try {
        Rep rep = responseQueue.take();
        result.complete(rep);
    } catch (Exception e) {
        result.completeExceptionally(e);
    }
}).start();

I know the 2nd one does not use the executorService, but I feel the whole point of using CompletableFuture is utilizing the CompletionStage APIs in functional-style.

like image 41
derrdji Avatar answered Oct 13 '22 01:10

derrdji


@antak mentioned it buried in a comment, but I think the correct answer here is:

For CompletableFuture.supplyAsync() wrap it in java.util.concurrent.CompletionException and rethrow it.

So the sample code would look something like:

CompletableFuture.supplyAsync(
    () -> {
        transporter.write(req);
        try {
            //here take the value from a blocking queue,will throw a interruptedException
            return responseQueue.take();
        }
        catch (InterruptedException e) {
            throw new CompletionException(e);
        }
    },  executorService);
like image 34
xbakesx Avatar answered Oct 13 '22 01:10

xbakesx