Может ли java system.in работать вместе с входным исходным кодом одновременно без использования потока

Говоря мое требование: либо пользователь вводит что-то в консоль (из system.in), либо сокет получает что-то, переходите к следующему шагу.

Итак, у меня есть сканер

Scanner sc = new Scanner(System.in);

Иметь UDP-клиент. (другой источник ввода)

DatagramSocket clientSocket = new DatagramSocket();

Мой код

while (true) {
     if (sc.hasNext()) {
        String str = sc.next();
        proceed(str)
     } else { 
        clientSocket.receive(pack);
        proceed(pack)
     }
}

Очевидно, что этот код не будет работать. Потому что при проверке sc.hasNext() java ожидает, что пользователь введет какой-либо ввод в консоли. В настоящее время я могу открыть поток для клиента Udp. Если я изменю порядок,

while (true) {
         clientSocket.receive(pack);
         if (not receive)  read from system.in
    }

Это не имеет смысла, так как Receive() будет продолжать ждать, пока не получит что-то, он никогда не будет одновременно читать из system.in.

Итак, как я могу выполнить свое требование без использования потока?

Вдохновленный ответом @Andriy Kryvtsun, я провел быстрый тест. По его словам, это каким-то образом использует неблокирующее чтение и позволяет продолжать тайм-аут сокета для эмуляции

        InputStream ins = System.in;
    byte buffer[] = new byte[512];
    BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
    DatagramSocket clientSocket = new DatagramSocket();
    System.out.println("From buffer:" + clientSocket.getLocalPort());

    while (true) {
        try {
            if (ins.available() > 0) {
                String line = reader.readLine();
                System.out.println("Read:" + line);
            } else {

                DatagramPacket pack = new DatagramPacket(buffer,buffer.length);
                clientSocket.setSoTimeout(2000);
                clientSocket.receive(pack);
                System.out.println("Receive: " + new String(pack.getData()));
            }
        } catch (IOException e1) {

        }
    }

person TTTTTAAOOOO    schedule 24.03.2016    source источник
comment
System.in — это блокирующий поток, поэтому нет ограничений на то, как долго он может блокироваться. Вам нужно использовать поток (или два) для обработки сокетов.   -  person Peter Lawrey    schedule 24.03.2016
comment
Похоже, вы захотите использовать что-то из пакета java.nio.channels, но я не знаю, что именно, потому что сам никогда этим не пользовался. Я бы использовал потоки для решения проблемы, которую вы описываете.   -  person Solomon Slow    schedule 24.03.2016
comment
да. Я также нашел эти неблокирующие вещи. Поскольку требование не использовать нить. Я должен найти неблокирующий способ.   -  person TTTTTAAOOOO    schedule 24.03.2016


Ответы (1)


Используйте вызов метода разблокировки InputStream#available(), чтобы получить информацию о том, что что-то готово для чтения перед использованием вызова блокировки Scanner#hasNext().

Также вы можете вызвать DatagramSocket#setSoTimeout(int timeout) перед вызовом метода блокировки receive(DatagramPacket p). Таким образом, вы можете прервать бесконечное ожидание внутри receive метода после timeout периода, эмулируя разблокировку чтения.

person Andriy Kryvtsun    schedule 24.03.2016
comment
Спасибо, Андрей, полезно. Я разместил свой код здесь. Единственное, если я устанавливаю тайм-аут на 2 секунды, когда я что-то набираю в консоли, мне приходится ждать около 1 секунды, чтобы распечатать это. Потому что он ждет тайм-аут. Я думаю, это то, чего мы не можем избежать. Пожалуйста, поправьте меня, если я ошибаюсь. - person TTTTTAAOOOO; 24.03.2016