简体   繁体   English

CompletableFuture 在超时时未完成

[英]CompletableFuture does not complete on timeout

I have a method read that reads from input stream.我有一个方法read从输入流中读取。 I want to complete the future if read has not finished after timeout.如果超时后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();
} 

But when I run this code, it does not finish by timeout and waits for input stream anyway.但是,当我运行此代码时,它不会在超时前完成并等待输入流。

There's at least two problems with your code:您的代码至少有两个问题:

  1. Nothing is being executed.什么都没有被执行。 You create a CompletableFuture and then invoke thenRunAsync on it.您创建一个CompletableFuture ,然后在其上调用thenRunAsync The stage created by thenRunAsync will only trigger once the previous stage has completed. thenRunAsync创建的阶段只会在前一阶段完成后触发。 Since you never complete the original CompletableFuture this will never happen.由于您从未完成原始CompletableFuture因此这永远不会发生。 You also end up joining on a future that will never complete.你也最终加入了一个永远不会完成的未来。

  2. You're joining on the wrong CompletableFuture .你加入了错误的CompletableFuture Methods such as thenRunAsync and orTimeout return a new instance which creates a sort of "chain" of stages. thenRunAsyncorTimeout等方法返回一个新实例,该实例创建了一种“阶段链”。 Each stage is triggered by the completion of its "parent" stage.每个阶段都由其“父”阶段的完成触发。 To fully understand this I recommend reading the documentation of CompletionStage .为了完全理解这一点,我建议阅读CompletionStage的文档。

Here's an example of your code working how I suspect you want:这是您的代码如何工作的示例,我怀疑您想要:

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

Some notes:一些注意事项:

  • Used CompletableFuture#runAsync(Runnable) to create a "primordial" stage.使用CompletableFuture#runAsync(Runnable)创建一个“原始”阶段。 This stage will complete when the Runnable completes and the common ForkJoinPool is used to execute the Runnable .Runnable完成并且公共ForkJoinPool用于执行Runnable时,此阶段将完成。

  • If and when thrown, the UncheckedIOException in the runAsync stage will cause the stage to complete exceptionally.如果,扔的时候,在UncheckedIOExceptionrunAsync阶段将导致阶段格外完成。

  • The #join() method is invoked on the instance returned by the orTimeout(1L, TimeUnit.SECONDS) call. #join()方法在orTimeout(1L, TimeUnit.SECONDS)调用返回的实例上调用。 Now if the timeout elapses the call to join() will throw a CompletionException wrapping a TimeoutException .现在,如果超时过去,则调用join()将抛出一个CompletionException包装TimeoutException

Warning: The call to read is not interrupted 1 when the timeout elapses, meaning it will continue to execute in the background.警告:当超时过去时, read调用不会被中断1 ,这意味着它将继续在后台执行。 This is due to the fact CompletableFuture has no reference to the executing threads and thus cannot interrupt them.这是因为CompletableFuture没有对正在执行的线程的引用,因此不能中断它们。


1. Assuming an interruption would even have an effect . 1. 假设中断甚至会产生影响

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

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