java - 使用 future 和 completableFuture 中断读取方法

标签 java future completable-future

在解决任务时,我注意到一种我无法解释的行为。

我的任务是从 InputStream 读取数据并在超时后中断读取。尽管很多人说阻塞读取不能被中断,但我已经使用 CompletableFuture

实现了这个目标
public void startReader() {
   CompletableFuture<Void> future = CompletableFuture.runAsync(() -> doRead(System.in));
   future.get(5, TimeUnit.SECONDS);
}

private void doRead(InputStream in) {
   try {
      new BufferedReader(new InputStreamReader(in)).readLine();
   } catch (IOException e) {
      e.printStackTrace();
   }
}

但是当我使用Future实现相同的操作时,我可以看到TimeoutException被抛出到JVM中,但我仍然可以看到读取线程没有终止并且仍在运行。

public void startReader() throws ExecutionException, InterruptedException, TimeoutException {
   Future<?> future = Executors.newSingleThreadExecutor().submit(() -> doRead(System.in));
   future.get(5, TimeUnit.SECONDS);
}

private void doRead(InputStream in) {
   try {
      new BufferedReader(new InputStreamReader(in)).readLine();
   } catch (IOException e) {
      e.printStackTrace();
   }
}

为什么会有这样的差异?我相信 CompletableFuture 不会产生任何魔法

最佳答案

当您到达 future.get(5, TimeUnit.SECONDS); 时,您的代码片段都不会停止“读取”线程。他们将继续等待您来自 System.in 的输入。如果你想停止它,你应该向该线程发送一个中断,并希望线程对其使用react。或者你可以强制终止线程,显然。

但是,CompletableFuture.runAsync()Executors.newSingleThreadExecutor() 调用使用不同的线程,特别是使用不同的 daemon标志(参见 What is a daemon thread in Java? )。当您在 doRead() 方法中放置 System.out.println(Thread.currentThread().isDaemon()); 时,您将看到 CompletableFuture. runAsync 使用守护线程(因此它不会阻止 JVM 终止),而 Executors.newSingleThreadExecutor() 则不会(并保持 JVM 处于 Activity 状态)。

关于java - 使用 future 和 completableFuture 中断读取方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60457319/

相关文章:

java - java中的类定义

java - Future 任务什么时候完成

Java CompletableFuture 链调用接口(interface)

Java 8 - 在 CompleteableFuture 的 thenCompose 方法中处理元素列表

java - 在 future list 上流式传输的最有效方式

java - 如何在Java中正确使用方法结果

java - 如何在关闭它并将其写入磁盘之前获取 ParquetWriter 对象的内存大小?

java - 如何根据先前的选择从下拉列表中进行选择?

rust - 从 channel 读取并使用 poll_fn 和 try_ready 的 Tokio future 永远不会完成

scala - 用 Future 满足抽象特征要求