带有Future和completableFuture的中断读取方法

问题描述 投票:0回答:1

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

我的任务是从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个回答
0
投票

当您到达future.get(5, TimeUnit.SECONDS);时,您的代码段都不会停止“读取”线程。他们将继续等待您从System.in输入。如果要停止它,则应向该线程发送一个中断,并希望该线程对此做出反应。或者,您也可以强行杀死线程。

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

© www.soinside.com 2019 - 2024. All rights reserved.