2016-04-26 94 views
3

我想看到的行爲有意地導致與CompletableFuture堆棧溢出,但相反發現,它導致成功和我的遞歸循環剛剛停止並退出和junit測試通過。這真的不是我想要的行爲。我想要一個失敗的快速行爲,所以我知道要修復我的代碼。CompletableFuture故意吹堆棧不會產生堆棧溢出?

@Test 
public void testBlowTheStack() throws InterruptedException { 
    recurse(0); 

    System.out.println("done"); 
    Thread.sleep(5000); 
} 


private void recurse(int counter) { 
    CompletableFuture<Integer> future = writeData(counter); 
    future.thenAccept(p -> recurse(p+1));  
} 

private CompletableFuture<Integer> writeData(int counter) { 
    System.out.println("counter="+counter); 
    if(counter == 1455) { 
     System.out.println("mark"); 
    } 

    CompletableFuture<Integer> future = new CompletableFuture<Integer>(); 
    future.complete(counter); 
    return future; 
} 

我試着在eclipse調試各地數1455,但日食凍結,所以我找不到這種行爲背後的原因無法加載堆棧跟蹤。

所以我的問題很簡單

  1. 是我的代碼以某種方式不正確?
  2. CompletableFuture如何成功退出(或者在這種情況下,我的junit測試用例如何傳遞)。

也許操作系統事關...我在Mac上。我以前有過自己的家鄉承諾,並且成功地打了一堆。

回答

1

thenAccept需要Consumer並返回CompletableFuture<Void>。如果消費者毫無例外地正常返回,那麼無效的未來將以空值完成。如果消費者拋出異常,那麼未來將異常完成。

如果你想趕上StackOverflowException你需要從返回的未來。有很多方法可以做到這一點。例如:

future.thenAccept(p -> recurse(p+1)).join(); 

future.thenAccept(p -> recurse(p+1)) 
     .exceptionally(e -> { 
      e.printStackTrace(); 
      return null; 
     }); 
+0

啊,當然......是有道理的例外是被抓....涼,是比較我所期待的。 –

+0

嗯,我將不得不測試stackoverflow,然後調用exceptionlly方法(和強制堆棧溢出那裏)..我不知道如何處理。 –

+0

我還沒有嘗試過,但是我對Java API文檔的解釋是,第二個異常將會丟失,未來將會與原始異常一起完成。換句話說,如果「異常」拋出異常,這是一個noop。 –