[英]Throwing exception from CompletableFuture hangs get() and join() in Java 17
[英]CompletableFuture exception behavior with join() then get()
我的直覺是以下代碼是錯誤的。 我相信因為正在使用join(),所以在完成期貨時拋出的任何異常都將被取消選中。 然后,當調用get()時,將不會檢查異常,不記錄任何錯誤,並且在故障期間難以診斷錯誤。
List<CompletableFuture> list = ImmutableList.of(future1, future2);
CompletableFuture.allOf(list.toArray(new CompletableFuture[list.size()])).join();
try {
result1 = future1.get();
result2 = future2.get();
} catch (InterruptedException | ExecutionException e) {
// will this ever run if join() is already called?
}
我查看了CompletableFuture的文檔,但沒有找到我的問題的確切答案。 我在這里問,然后將閱讀源代碼。
我可以看到catch塊代碼運行的唯一原因是,如果以某種方式檢查異常可以保存在某些執行上下文中而不是在join()中拋出(或者由未經檢查的異常包裝拋出),然后以某種形式再次拋出得到()。 這對我來說似乎不太可能。
所以我的最終問題是,catch塊代碼是否會運行?
join
和get
方法都是阻塞方法,它依賴於完成信號並返回結果T
處理有問題的代碼片段: -
一方面,當線程在等待過程中被中斷時,可能會拋出InterruptedException
,因為我們執行get
,此處的等待已經由join
方法完成。
另外,如join
方法文檔中所述
/**
* ... if a
* computation involved in the completion of this
* CompletableFuture threw an exception, this method throws an
* (unchecked) {@link CompletionException} with the underlying
* exception as its cause.
*/
因此,另一方面,只有在未來異常完成的情況下,才會拋出針對futureN.get()
的ExecutionException
。 由於未來如果異常執行將最終為join
調用拋出CompletionException
,它將不會到達catch塊或為此try
阻止。
是的,代碼永遠不會到達,但這並不會使“代碼錯誤”。
首先,我們來試試吧......
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
throw new IllegalArgumentException();
});
try
{
CompletableFuture.allOf(future1).join();
}
catch (Exception e1)
{
System.out.println("I'd exit here."); // *1
}
try
{
future1.get();
}
catch (InterruptedException | ExecutionException e)
{
System.out.println("Entered!");
}
由於你沒有執行try/catch
“* 1”,因此Exception會導致方法退出並且永遠不會到達get()
; 所以第二個catch
子句永遠不會執行。
但是, catch
仍然是必要的,因為它是編譯器,它無法知道先前的調用序列。
無論如何,更直接的方式是這樣的:
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
throw new IllegalArgumentException();
});
try
{
CompletableFuture.allOf(future1).join();
future1.get();
}
catch (CompletionException e1) // this is unchecked, of course
{
System.out.println("Exception when joining");
}
catch (InterruptedException | ExecutionException e)
{
System.out.println("Exception when getting");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.