Java:如何中止从System.in读取的线程

我有一个Java线程:

class MyThread extends Thread { @Override public void run() { BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); String msg; try { while ((msg = stdin.readLine()) != null) { System.out.println("Got: " + msg); } System.out.println("Aborted."); } catch (IOException ex) { ex.printStackTrace(); } } } 

}

在另一个线程中,如何在此线程中中止stdin.readline()调用,以便此线程打印Aborted. ? 我尝试过System.in.close() ,但这没有任何区别, stdin.readline()仍在阻塞。

我对没有的解决方案感兴趣

  • 忙着等待(因为这会烧掉100%的CPU);
  • 睡觉(因为那时程序不会立即响应System.in )。

我的第一反应是一个线程System.in真的没有在一起。

首先,将其拆分,以便线程代码不会触及包括System.in在内的任何静态代码。

线程从InputStream读取并传递到缓冲区。 将InputStream传递到从缓冲区读取的现有线程中,但也检查您是否已中止。

Heinz Kabutz的新闻通讯显示了如何使用缓冲区和ExecutorService中止System.in读取。

现在,我不知道这种方法是否泄漏,不是便携式还是有任何非明显的副作用。 就个人而言,我不愿意使用它。

您可以使用NIO通道和文件描述符做一些事情 – 我自己的实验并没有产生任何结果。

怎么样…

 private static BufferedReader stdInCh = new BufferedReader( new InputStreamReader(Channels.newInputStream(( new FileInputStream(FileDescriptor.in)).getChannel()))); 

调用stdInch.readline()线程现在是可中断的,readline()将抛出java.nio.channels.ClosedByInterruptException

JavaDoc for BufferedReader.readLine :

返回:包含行内容的String,不包括任何行终止字符;如果已到达流末尾,则返回null

基于此,我不认为它将永远返回null(System.in实际上是否可以关闭,我不认为它会返回流的结尾?),因此while循环不会终止。 停止线程的常用方法是在循环条件中使用布尔变量并从线程外部更改它,或者调用Thread-objects的interrupt()-method(仅当线程为wait()时才有效:ing或ing sleep():ing,或者在抛出InterruptedException的阻塞方法中)。 您还可以使用isInterrupted()检查线程是否已被中断。

编辑:这是一个使用isInterrupted()interrupt()的简单实现。 主线程在中断工作线程之前等待5秒。 在这种情况下,工作线程基本上是忙等待的,所以它不是那么好(一直循环并检查stdin.ready() ,当然如果没有输入准备好,你可以让工作线程hibernate一段时间):

 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class MyThreadTest { public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); try { Thread.sleep(5000); } catch(InterruptedException e) { //Do nothing } myThread.interrupt(); } private static class MyThread extends Thread { @Override public void run() { BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); String msg; while(!isInterrupted()) { try { if(stdin.ready()) { msg = stdin.readLine(); System.out.println("Got: " + msg); } } catch(IOException e) { e.printStackTrace(); } } System.out.println("Aborted."); } } } 

如果它在readline上被阻塞,或者至少我找不到一个(使用System.in),似乎没有办法实际中断BufferedReader。

你有没有尝试过:

 Thread myThread = new MyThread(); myThread.start(); // your code. myThread.interrupt(); 

中断方法将抛出InterrupedtException,之后您可以处理代码。

如何在上面的线程类定义中定义一个字段,如:

 class MyThread extends Thread { protected AtomicBoolean abortThread = new AtomicBoolean(false); public void doAbort() { this.abortThread.set(true); } @Override public void run() { ... if (this.abortThread.get()) { ...something like break loop... } } }