3

我试图查看故意导致 CompletableFuture 堆栈溢出的行为,但发现它导致了成功,并且我的递归循环刚刚停止并退出,并且 junit 测试通过了。这真的不是我想要的行为。我想要一个快速失败的行为,所以我知道要修复我的代码。

@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,但 Eclipse 冻结并且无法加载堆栈跟踪,所以我找不到这种行为背后的原因。

所以我的问题很简单

  1. 我的代码是否不正确?
  2. CompletableFuture 如何成功退出(或者在这种情况下我的 junit 测试用例如何通过)。

也许操作系统很重要……我在 Mac 上。我以前有自己的本土承诺,而那些成功地打破了堆栈。

4

1 回答 1

2

thenAccept接受 aConsumer并返回 a CompletableFuture<Void>。如果消费者正常返回无异常,则 void 未来以 null 完成。如果消费者抛出异常,则未来会以异常方式完成该异常。

如果你想抓住它,StackOverflowException你需要从返回的未来中获取它。有很多方法可以做到这一点。例如:

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

或者

future.thenAccept(p -> recurse(p+1))
      .exceptionally(e -> {
          e.printStackTrace();
          return null;
      });
于 2016-04-26T14:09:04.723 回答