Java JDK8 CompletableFuture.supplyAsync如何处理中断异常
处理interruptedException的常用方法是再次中断或直接抛出interruptedException,但两者都不能工作。有人有这个想法吗 由于lambda函数不支持抛出异常,我认为Java开发人员需要一种新的范例。我想到的一件事如下: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
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);