簡體   English   中英

使用join()然后get()的CompletableFuture異常行為

[英]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塊代碼是否會運行?

joinget方法都是阻塞方法,它依賴於完成信號並返回結果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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM