【问题标题】:How to properly interrupt a Java thread which is reading user input?如何正确中断正在读取用户输入的 Java 线程?
【发布时间】:2015-06-28 12:20:29
【问题描述】:

我有一个耗时的任务compute(),我想在用户输入“abort”时手动中止。

为此,我有一个 Runnable InputAbort 使用无限循环和一个 BufferedReader 来扫描用户输入。当用户决定不中止长时间的计算时,就会出现问题。在这种情况下,运行InputAbort 的线程不会被正确中断,从而阻止 JVM 完成(使线程成为守护进程确实可以工作,但我认为必须有一种方法可以正确结束线程)。

当用户输入“abort”中止计算时,问题不会发生。当我删除 Runnable 中的 s = br.readLine(); 行并且用户等待计算完成时,它也不会发生。

启动线程和计算:

ComputationObject co = new ComputationObject();

Runnable rInputAbort = new InputAbort(co);
Thread tInputAbort = new Thread(rInputAbort);

tInputAbort.start();
co.compute();
tInputAbort.interrupt();

可运行:

public class InputAbort implements Runnable {
    private ComputationObject co;

    public RunnableInputAbort(ComputationObject co) {
        this.co = co;
    }

    @Override
    public void run() {
        try {
            InputStreamReader isr = new InputStreamReader(System.in);
            BufferedReader br = new BufferedReader(isr);
            String s = "";

            while ( ! Thread.currentThread().isInterrupted() ) {
                s =  br.readLine();
                if ( s.equals("abort") ) {
                    co.abort();
                    Thread.currentThread().interrupt();
                }
            }

            br.close();
            isr.close();

        }  catch (Exception e) {
            e.printStackTrace();
        }
    }

}

【问题讨论】:

  • How to timeout a thread的可能重复
  • 这个问题不是简单地询问如何使线程超时;读取输入的线程也必须响应中断信号,即使它在读取时被阻塞。
  • 我知道这不能回答问题,但用户通过命令行停止进程是否必要?过去,我使用文件的存在作为用户与进程通信的一种方式。我知道不理想,但这将是一个解决方案。用户发出“touch stop.stop”以在预期的位置创建一个文件,然后进程终止,因为它已经看到该文件在那里。

标签: java multithreading bufferedreader


【解决方案1】:

您不能中断正在读取输入的线程。见How to stop a thread waiting in a blocking read operation in Java?

如果你只想退出 JVM,你可以这样做:

System.exit(0)

【讨论】:

  • NP - 可能应该作为重复关闭。
【解决方案2】:

BufferedReader 上检查ready() 为我解决了这个问题:

while ( ! Thread.currentThread().isInterrupted() ) {
    if ( br.ready() ) {
        s =  br.readLine();
        if ( s.equals("abort") ) {
            cb.doAbort();
            Thread.currentThread().interrupt();
        }
    }
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}

更多信息在这里(即使我的问题真的与超时无关):

Is it possible to read from a InputStream with a timeout?

【讨论】:

  • 非常非常糟糕的主意。线程将在循环中旋转,等待输入并占用 CPU。
  • 我不太明白这个问题。这已经是原始实现中的一个缺陷,还是问题来自对 ready() 的检查?在循环中的某处添加 sleep(1000) 会有所帮助吗?
  • 您可以在循环结束时添加睡眠,这会有所帮助。如果您没有睡眠,它将不断循环,并且您的 CPU 使用率将在一个内核上达到 100%。
  • 好的,谢谢。澄清一下:这与br.ready() 没有任何关系,对吧?
  • 是的。说没有输入,br.ready() 返回false,你就到循环的顶部;线程没有中断,您继续并再次检查 br.ready() 等等,无数次,直到有人键入某些内容或程序完成。
猜你喜欢
  • 1970-01-01
  • 2021-03-07
  • 1970-01-01
  • 2018-08-09
  • 2012-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多