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

时间:2011-05-15 11:42:43

标签: java stdio

我有一个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)。

6 个答案:

答案 0 :(得分:8)

Heinz Kabutz's newsletter显示了如何使用bufferExecutorService中止System.in次读取。

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

您可以使用NIO channelsfile descriptors执行某些操作 - 我自己的实验并未产生任何结果。

答案 1 :(得分:3)

怎么样......

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

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

答案 2 :(得分:2)

我的第一反应是线程System.in真的不能在一起。

首先,将其拆分,使线程代码不会触及任何静态内容,包括System.in

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

答案 3 :(得分:1)

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(),当然如果没有输入准备就可以让工作线程休眠一段时间):

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。

答案 4 :(得分:0)

你试过了吗?

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

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

答案 5 :(得分:-1)

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

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...
    }
  }
}