CompletableFuture的单独异常处理

xen*_*ide 9 java java-8 completable-future

我意识到我希望我们的API的消费者不必处理异常.或者更清楚一点,我想确保始终记录异常,但只有消费者才知道如何处理成功.我希望客户端能够处理异常,如果他们想要的话,File我无法返回它们.

注意:FileDownload是一个Supplier<File>

@Override
public CompletableFuture<File> processDownload( final FileDownload fileDownload ) {
    Objects.requireNonNull( fileDownload );
    fileDownload.setDirectory( getTmpDirectoryPath() );
    CompletableFuture<File> future = CompletableFuture.supplyAsync( fileDownload, executorService );
    future... throwable -> {
        if ( throwable != null ) {
            logError( throwable );
        }
        ...
        return null; // client won't receive file.
    } );
    return future;

}
Run Code Online (Sandbox Code Playgroud)

我真的不明白这些CompletionStage东西.我使用exceptionhandle?我会回归原来的未来还是他们回来的未来?

Jef*_*rey 14

假设您不想影响您的结果CompletableFuture,您将需要使用CompletableFuture::whenComplete:

future = future.whenComplete((t, ex) -> {
  if (ex != null) {
    logException(ex);
  }
});
Run Code Online (Sandbox Code Playgroud)

现在,当您的API的消费者尝试调用时future.get(),他们将获得异常,但他们不一定需要对其执行任何操作.


但是,如果您想让您的消费者不知道异常(nullfileDownload失败时返回),您可以使用CompletableFuture::handle或者CompletableFuture::exceptionally:

future = future.handle((t, ex) -> {
  if (ex != null) {
    logException(ex);
    return null;
  } else {
    return t;
  }
});
Run Code Online (Sandbox Code Playgroud)

要么

future = future.exceptionally(ex -> {
  logException(ex);
  return null;
});
Run Code Online (Sandbox Code Playgroud)

  • 这更容易.消费者对异常一无所知可以使用`future.thenAccept`进行简单链接.这里的关键点是,在特殊情况下永远不会调用消费者,因此它既不需要处理异常,也不需要处理"null"值.底线是,不要使用`get()`... (4认同)