Java 奇怪的线程行为

Java 奇怪的线程行为,java,multithreading,Java,Multithreading,我正在尝试这样做:问题显示在控制台中。如果在一段时间内用户没有写出答案,则会询问下一个问题。如果用户输入答案,将立即询问下一个问题。我的代码: public class Test { private boolean stopQuestion; Thread scannerThread = new Thread(); public static void main(final String[] args) { final Test test = new Test();

我正在尝试这样做:问题显示在控制台中。如果在一段时间内用户没有写出答案,则会询问下一个问题。如果用户输入答案,将立即询问下一个问题。我的代码:

public class Test {
private boolean stopQuestion;
Thread          scannerThread = new Thread();

public static void main(final String[] args) {
    final Test test = new Test();

    test.scannerThread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                String string;
                do {
                    string = test.requestInput(new Thread(new Runnable() {

                        @Override
                        public void run() {
                            try {
                                Thread.sleep(3000);
                            } catch (final InterruptedException e) {
                            }
                            test.scannerThread.interrupt();

                        }
                    }));
                } while (!test.stopQuestion);

                System.out.println("Input: " + string);
            } catch (final IOException e) {
                throw new RuntimeException(e);
            }
        }
    });
    test.scannerThread.start();

}

public String requestInput(final Thread timer) throws IOException {
    final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    timer.start();

    System.out.println("Any question");
    System.out.println("Please type your answer: ");
    try {
        while (!br.ready()) {
            Thread.sleep(100);
        }
    } catch (final InterruptedException e) {
        System.out.println("Time is over. Next question: ");
        return null;
    }
    System.out.println("Thank You for providing input!");
    return br.readLine();
}
}

如果您没有向控制台写入任何内容,那么一切似乎都按预期工作。时间结束了,下一个问题被问到了。但是,如果有东西被写入控制台,计时器开始出现故障,下一个问题不会等待指定的时间量,有时根本不会等待。我不明白发生了什么事


我在方法外部创建了线程实例,并将实例作为引用传递给该方法,但随后抛出IllegalThreadStateException。

我发现您的代码存在两个主要问题:

  • 您正在持续创建应该读取输入的线程:

                do {
                    string = test.requestInput(new Thread(new Runnable() {
    
                        @Override
                        public void run() {
                            try {
                                Thread.sleep(3000);
                            } catch (final InterruptedException e) {
                                e.printStackTrace();
                            }
                            test.scannerThread.interrupt();
    
                        }
                    }));
                } while (!test.stopQuestion); // <-- this is always true
    

  • 此外,您没有关闭任何这些
    BufferedReader
    实例。

    这里似乎有一些错误,但突出的两个主要问题是
    stopQuestion
    的可见性以及从多个线程访问
    System.in
    的整个想法。哦,而且
    sleep()
    也不能用于精确计时,绝对没有任何保证。此外,如果用户键入了一半答案,然后您打印了另一个问题,那么键入的文本仍然存在于输入缓冲区中,这将非常混乱。你的前提是有缺陷的,即你试图做的是不使用控制台程序。我刚刚注意到你使用
    interrupt()
    进行重复的信号发送,这听起来也不是一个好主意。如果你关闭
    BufferedReader
    ,你就关闭了
    系统,并防止以后读取所有输入。不要关闭包裹在
    系统中的读卡器/扫描仪/输入流。
    中应该只有一个
    BufferedReader
    实例,并且最终应该关闭它。永远不要关闭它
    System.in
    由Java运行时管理,应用程序不应关闭它。有关于它的源代码吗?我查找了一些源代码,在应用程序终止之前关闭
    BufferedReader
    似乎是一个好主意。如果您直接从
    System.in
    读取,即未包装,您是否还会在程序末尾添加
    System.in.close()
    ?很可能不会,因为你没有打开它。那么,为什么您认为关闭
    系统是一个“好主意”
    仅仅因为您将其包装在帮助程序中,使其更易于阅读文本?你“好主意”的来源是什么?
    final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));