Java JDK8 CompletableFuture.supplyAsync如何处理中断异常

Java JDK8 CompletableFuture.supplyAsync如何处理中断异常,java,exception,lambda,java-8,Java,Exception,Lambda,Java 8,处理interruptedException的常用方法是再次中断或直接抛出interruptedException,但两者都不能工作。有人有这个想法吗 由于lambda函数不支持抛出异常,我认为Java开发人员需要一种新的范例。我想到的一件事如下: CompletableFuture.supplyAsync( () -> { transporter.write(req); //here take the value from a blocking queue,will th

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

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

CompletableFuture.supplyAsync(
() -> {
    transporter.write(req);
    //here take the value from a blocking queue,will throw a interruptedException
    return responseQueue.take();
},  executorService);
公共类ResultWrapper{
E例外;
R结果;
}
Lambda函数可以返回此包装器的实例。(编辑:您的案例)

completablefutureafuture=。。。;
...
未来供应同步(
() -> {
试一试{
传输写入(req);
}捕捉(中断异常e){
ResultWrapper r=新的ResultWrapper();
r、 例外=e;
r、 结果=空;
返回r;
}
...
}(执行人服务);

我这样更改代码

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);
CompletableFuture结果=新的CompletableFuture();
CompletableFuture.runAsync(()->{
传输写入(req);
试一试{
Rep Rep=responseQueue.take();
结果:完成(rep);
}捕捉(中断异常e){
结果:异常完全(e);
Thread.currentThread().interrupt();
}捕获(例外e){
结果:异常完全(e);
}
}(执行人服务);
返回结果;

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

1(我最后做的事情):

或2:

CompletableFuture.runAsync(() -> {
    transporter.write(req);
    try {
        Rep rep = responseQueue.take();
        result.complete(rep);
    } catch (Exception e) {
        throw new CompletionException(e);
    }
}, executorService);
return result;
CompletableFuture结果=新的CompletableFuture();
新线程(()->{
传输写入(req);
试一试{
Rep Rep=responseQueue.take();
结果:完成(rep);
}捕获(例外e){
结果:异常完全(e);
}
}).start();

我知道第二个没有使用
executorService
,但我觉得使用CompletableFuture的全部意义在于以功能性的方式使用CompletionStage API

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

对于
CompletableFuture.supplyAsync()
将其包装在
java.util.concurrent.CompletionException
中并重新显示

因此,示例代码如下所示:

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


“但两者都不能工作。”=>为什么?两者都有编译器错误。若直接抛出异常,编译器将显示未处理的异常,若捕获并调用ad.current.interrupt,编译器将显示必须返回T类型。是,您需要返回或抛出。如果您决定返回null,例如:
尝试{return queue.take();}catch(InterruptedException e){Thread.currentThread().interrupt();return null;}
假设future表示一个正常值或异常的计算结果,我觉得这应该是一种将异常设置为future的方法,我认为lambda函数不支持抛出异常,所以抛出异常是不可能的。在这里,您可以做的唯一一件事是返回某些内容。如果您认为这对您有帮助,请将其标记为“答案:”),而不是将异常转换为返回值,您应该将它们包装在未检查的异常中,并在必要时在外部将其转换回已检查的异常。在整个过程中将异常作为异常保留。返回值是为非错误条件保留的。虽然我在某种程度上同意,考虑生产者/消费者场景,其中生成/消费对象是lambda函数。消费者必须捕获未经检查的异常,因为生产者可能抛出了未经检查的异常以偷偷输出已检查的异常。我不知道哪一个更糟,我想是Java太差劲了。不要重新发明轮子。。对于
CompletableFuture.supplyAsync()
将其包装在
java.util.concurrent.CompletionException
中,然后重新播放。您所做的与我所做的相同。唉,
CompletableFuture result
可以被任何符合“结果或异常”范式的类所取代。例如,您可以将
get
complete
completeeexceptional
方法添加到
resultrapper
中,并使用
resultrapper rep=new resultrapper()。非常巧合的是,您使用
CompletableFuture
遇到了这个lambda函数限制,并且再次使用
CompletableFuture
解决了它,使用了您使用的那些方法。是的,但是CompletableFuture已经有了计算结果的抽象,因此,我不想为同一类型创建新类型。如果您与其他人一起工作,这可能会使代码的读者感到困惑。如果不是的话,这对您来说很好。这是因为future和promise在java中将两个概念合并为一种类型completablefuture。返回completablefuture可能会使所有调用都异步,因为其中有许多方法。completablefuture.runAsync在这里实际上不需要使用,因为您没有使用返回值;如果您想保存一些周期,可以创建ForJoinTask并在ForkJoinPool#commonPool中执行它。它的代码稍微多一些,但您将避免创建几个实例和写入易失性字段,因此它的性能应该更好。您的第二个解决方案可以改进。请参阅详细解释。第二种解决方案效率很低,我希望你不要每次想运行异步代码时都启动一个新线程。这里有没有其他方法可以避免try catch?我不这么认为。您可以创建自己的BlockingQueue实现,它抛出
CompletionException
,而不是
interruptedeexception
。。。但这似乎对你没什么帮助。
CompletableFuture.runAsync(() -> {
    transporter.write(req);
    try {
        Rep rep = responseQueue.take();
        result.complete(rep);
    } catch (Exception e) {
        throw new CompletionException(e);
    }
}, executorService);
return result;
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();
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);