【问题标题】:Interrupting read method with future and completableFuture用 future 和 completableFuture 中断读取方法
【发布时间】:2020-02-29 05:01:47
【问题描述】:

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

我的任务是读取 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 不会变魔术

【问题讨论】:

    标签: java future completable-future


    【解决方案1】:

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

    但是,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 活动)。

    【讨论】:

      猜你喜欢
      • 2016-05-21
      • 2021-07-31
      • 2015-11-03
      • 1970-01-01
      • 1970-01-01
      • 2019-09-01
      • 1970-01-01
      • 2022-01-12
      • 1970-01-01
      相关资源
      最近更新 更多