繁体   English   中英

CompletableFuture 在超时时未完成

[英]CompletableFuture does not complete on timeout

我有一个方法read从输入流中读取。 如果超时后read尚未完成,我想完成未来。

public static void main(String[] args) {
   CompletableFuture<?> future = new CompletableFuture<>();
   future
      .thenRunAsync(() -> {
         try {
            read(data);
         } catch (IOException e) {
            future.completeExceptionally(e);
         }
      })
      .orTimeout(1, TimeUnit.SECONDS);

   future.join();
} 

但是,当我运行此代码时,它不会在超时前完成并等待输入流。

您的代码至少有两个问题:

  1. 什么都没有被执行。 您创建一个CompletableFuture ,然后在其上调用thenRunAsync thenRunAsync创建的阶段只会在前一阶段完成后触发。 由于您从未完成原始CompletableFuture因此这永远不会发生。 你也最终加入了一个永远不会完成的未来。

  2. 你加入了错误的CompletableFuture thenRunAsyncorTimeout等方法返回一个新实例,该实例创建了一种“阶段链”。 每个阶段都由其“父”阶段的完成触发。 为了完全理解这一点,我建议阅读CompletionStage的文档。

这是您的代码如何工作的示例,我怀疑您想要:

public static void main(String[] args) {
  CompletableFuture.runAsync(
          () -> {
            try {
              read(data);
            } catch (IOException ex) {
              throw new UncheckedIOException(ex);
            }
          })
      .orTimeout(1L, TimeUnit.SECONDS)
      .join();
}

一些注意事项:

  • 使用CompletableFuture#runAsync(Runnable)创建一个“原始”阶段。 Runnable完成并且公共ForkJoinPool用于执行Runnable时,此阶段将完成。

  • 如果,扔的时候,在UncheckedIOExceptionrunAsync阶段将导致阶段格外完成。

  • #join()方法在orTimeout(1L, TimeUnit.SECONDS)调用返回的实例上调用。 现在,如果超时过去,则调用join()将抛出一个CompletionException包装TimeoutException

警告:当超时过去时, read调用不会被中断1 ,这意味着它将继续在后台执行。 这是因为CompletableFuture没有对正在执行的线程的引用,因此不能中断它们。


1. 假设中断甚至会产生影响

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM