JDK8 CompletableFuture.supplyAsync如何处理interruptedException

时间:2014-04-20 16:42:38

标签: java exception lambda java-8

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

处理interruptedException的常用方法是再次中断或直接抛出interruptedException,但两者都无法工作。有人有想法吗?

4 个答案:

答案 0 :(得分:13)

我改变了这样的代码。

    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;

答案 1 :(得分:3)

由于lambda函数不支持抛出异常,我认为Java开发人员需要一个新的范例。我想到的一件事如下:

public class ResultWrapper<R, E extends Exception> {
    E exception;
    R result;
}

Lambda函数可以返回此包装器的实例。 (编辑:你的情况)

CompletableFuture<ResultWrapper<String, InterruptedException>> aFuture = ...;
...
aFuture.supplyAsync(
() -> {
    try {
        transporter.write(req);
    } catch(InterruptedException e) {
        ResultWrapper<String, InterruptedException> r = new ResultWrapper<>();
        r.exception = e;
        r.result = null;
        return r;
    }
    ...
},  executorService);

答案 2 :(得分:2)

我遇到了同样的问题,但是在阅读了这里的评论和参考书之后,我认为你可以做以下两种中的任何一种:

1(我最终在做什么):

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

或2:

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

我知道第二个不使用executorService,但我觉得使用CompletableFuture的重点是在功能风格中使用CompletionStage API。

答案 3 :(得分:0)

@antak在评论中提到了它,但我认为这里的正确答案是:

  

对于CompletableFuture.supplyAsync(),请将其包装在java.util.concurrent.CompletionException中,然后将其重新扔出。

因此示例代码如下所示:

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);