Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中从控制台获取输入:是阻塞还是非阻塞?_Java_Java.util.scanner - Fatal编程技术网

在Java中从控制台获取输入:是阻塞还是非阻塞?

在Java中从控制台获取输入:是阻塞还是非阻塞?,java,java.util.scanner,Java,Java.util.scanner,我正在编写一个Java程序,在这个程序中,我从控制台读取一行代码,并围绕它进行一些处理。处理可能需要1-2秒(即比输入速率长),而我可能保持每秒接收50行 虽然也有一些类似的问题,但它们是针对C/C++而不是Java。因此,我的基本问题如下: 仍在处理输入/行时,是否阻止我接收新输入?或者它们以某种方式在系统/JVM中排队?或者最好这样问:当处理需要时间时,我是否会漏掉任何一行?我不想以任何方式漏掉任何一行 以下是我的代码片段: Scanner sc = new Scanner(System.i

我正在编写一个Java程序,在这个程序中,我从控制台读取一行代码,并围绕它进行一些处理。处理可能需要1-2秒(即比输入速率长),而我可能保持每秒接收50行

虽然也有一些类似的问题,但它们是针对C/C++而不是Java。因此,我的基本问题如下:

仍在处理输入/行时,是否阻止我接收新输入?或者它们以某种方式在系统/JVM中排队?或者最好这样问:当处理需要时间时,我是否会漏掉任何一行?我不想以任何方式漏掉任何一行

以下是我的代码片段:

Scanner sc = new Scanner(System.in);

while(sc.hasNext()){
    //process line. Can take 1-2 seconds.
    processInput(sc.nextLine());
}
sc.close();
更新:

正如建议的那样,我提出了使用
执行器使代码更加线程友好的方法:

ExecutorService executorService = Executors.newFixedThreadPool(10);
while (sc.hasNext()) {
        executorService.submit(new Runnable() {
            public void run() {
                processInput(sc.nextLine());
            }
        });
}

它是阻塞,尽管可能更清楚:它一直在说“扫描操作可能会阻塞等待输入”。虽然理论上它可以抛出NosTouchElementException而不是阻塞,但在我看来,这取决于实现。

只需比较这两个示例:

第一,线性,无多个螺纹:

public class SampleClass {

    public static void main(String[] args) {
        SampleClass instance = new SampleClass();
        instance.start();
    }

    private void start() {
        Scanner sc = new Scanner(System.in);
        String input;

        while (!(input = sc.nextLine()).equals("exit")) {
            processInput(input);
        }

        sc.close();
    }

    private void processInput(String input) {
        try {
            Thread.sleep(2000);
            System.out.println("input: " + input);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
然后,为每个输入处理使用一个新线程:

public class SampleClass {

    public static void main(String[] args) {
        SampleClass instance = new SampleClass();
        instance.start();
    }

    private void start() {
        Scanner sc = new Scanner(System.in);
        String input;

        while (!(input = sc.nextLine()).equals("exit")) {
            processInput(input);
        }

        sc.close();
    }

    private void processInput(String input) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                    System.out.println("input: " + input);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
    }

}

试试看。在这两种情况下,您都不会错过输入,但不同的是,如果没有新线程,处理时间会增加(当然)-它不会并行运行。

如果
processInput()
没有在另一个线程中运行内容,则会等待处理完成并获得下一行,然后重试。但是
系统中的
是一个数据流。你不会因为花时间从小溪里阅读而“漏掉”任何一行。@mumpitz说得好。我应该在新线程中运行
processInput
。只是想知道,这些即将发布的消息堆放在哪里?!:)@TinaJ他们不是;)在
process()
完成之前,您将无法输入另一行。因为只有在这之后,它才允许您输入下一行。我听说最好有一个执行者池,他们可以在那里执行
processInput
。有什么例子可以实现吗?@mumpitz yes no stacked…我的意思是输入是在控制台中输入的,但我仍然没有在我的代码中作为新行接收它们。那么他们同时在哪里缓冲?谢谢。问题更多的是:当处理需要时间时,我会错过任何输入吗?原则上不会。但请注意,“如果没有外部同步,扫描仪对于多线程使用是不安全的。”嗯,那个么,我该如何使我的代码片段高效呢?我听说了遗嘱执行人的事。如果有帮助的话,你可以发布一个示例吗?如果线程处理是在processInput中完成的,你可以使用一个执行器。@Jonathan在现实世界中你是100%正确的,但我认为它们不能更具体,因为阻塞是由OSTool完成的。是的,就是这样。但在这里你每秒钟就加一次线程,对吗?!你能检查我的更新,看看我对执行器的使用是否正确吗?每次收到新输入时,都会启动一个新线程。然后,该线程等待2秒钟,然后将输入打印到stdout并退出。我自己也没有和遗嘱执行人一起工作过,但看起来不错,而且非常实用。