简体   繁体   English

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

[英]Getting input from console in Java: Is it blocking or non-blocking?

I'm writing a Java program in which I read a line from Console, and do some processing around it.我正在编写一个 Java 程序,在其中我从控制台读取一行,并对其进行一些处理。 The processing might take 1-2 seconds (ie takes longer than the input rate), while I might keep receiving 50 lines per second.处理可能需要 1-2 秒(即比输入速率更长),而我可能会保持每秒接收 50 行。

Although there were some similar questions, they were addressing C/C++ and not Java.尽管有一些类似的问题,但它们是针对 C/C++ 而不是 Java。 So my fundamental question is below:所以我的基本问题如下:

While still processing an input/line, am I blocked from receiving new inputs?在仍在处理输入/线路时,我是否无法接收新输入? Or somehow they are queued in the system/JVM?或者它们以某种方式在系统/JVM 中排队? Or better ask this way: Do I miss any lines while processing takes time?或者最好这样问:处理需要时间时我是否遗漏了任何行? I don't want to miss any lines by any means.我不想以任何方式错过任何一行。

Here is my code snippet:这是我的代码片段:

Scanner sc = new Scanner(System.in);

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

UPDATE:更新:

As suggested, I came up with making my code more thread-friendly, using Executors :按照建议,我想出了使用Executors使我的代码更加线程友好的方法:

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

Just compare these two samples:只需比较这两个样本:

Frist, linear without multiple threads:首先,没有多线程的线性:

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();
        }
    }

}

Then, using a new thread for every input processing:然后,为每个输入处理使用一个新线程:

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();
    }

}

Just try it.就试一试吧。 In both cases you don't miss input, but the difference is that without new threads the processing time adds up (of course) - it doesn't run parallel.在这两种情况下,您都不会错过输入,但不同之处在于,如果没有新线程,处理时间会增加(当然) - 它不会并行运行。

It is blocking, although the documentation could have been clearer: It keeps saying "A scanning operation may block waiting for input."尽管文档可能更清楚,但它正在阻塞:它一直说“扫描操作可能会阻塞等待输入”。 While it could theoretically throw a NoSuchElementException instead of blocking, it seems to me that this is up to the implementation.虽然理论上它可以抛出 NoSuchElementException 而不是阻塞,但在我看来这取决于实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM