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

时间:2019-02-08 15:39:25

标签: java java.util.scanner

我正在编写一个Java程序,在该程序中,我从Console读取了一行,并对其进行了一些处理。处理过程可能需要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();

更新:

根据建议,我想出了使用Executors使我的代码对线程更友好的方法:

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

2 个答案:

答案 0 :(得分:1)

只需比较这两个示例:

第一个没有多个线程的线性拳头:

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

}

只需尝试一下。在这两种情况下,您都不会错过输入,但是不同之处在于,没有新线程的情况下(当然),处理时间加起来了-它不会并行运行。

答案 1 :(得分:0)

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