简体   繁体   中英

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. The processing might take 1-2 seconds (ie takes longer than the input rate), while I might keep receiving 50 lines per second.

Although there were some similar questions, they were addressing C/C++ and not 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? 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 :

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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