Java JDK8 CompletableFuture.supplyAsync 如何处理interruptedException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23184964/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 21:13:25  来源:igfitidea点击:

JDK8 CompletableFuture.supplyAsync how to deal with interruptedException

javaexceptionlambdajava-8

提问by GrapeBaBa

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?

常见的处理interruptedException的方法要么是再次中断,要么直接抛出interruptedException,但这两种方法都行不通。有人有这个想法吗?

采纳答案by GrapeBaBa

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;

回答by mostruash

As lambda functions don't support throwing exceptions, I think Java developers will need a new paradigm. One thing that comes to mind is as follows:

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

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

Lambda functions can return instances of this wrapper. (Edit: your case)

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

回答by derrdji

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

1(我最终在做什么):

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:

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

我知道第二个不使用executorService,但我觉得使用 CompletableFuture 的全部意义在于以函数式风格利用 CompletionStage API。

回答by xbakesx

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

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

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

为了CompletableFuture.supplyAsync()把它包装java.util.concurrent.CompletionException和重新抛出。

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