Search code examples
javamultithreadingsystem.in

Can java system.in work together with input source code at same time without using thread


Saying my requirement is: Either user type something in console (from system.in) or socket receive something, proceed to next step.

So I have a scanner

Scanner sc = new Scanner(System.in);

Have an Udp client. (a different input source)

DatagramSocket clientSocket = new DatagramSocket();

My code is

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

Obviously this code will not work. Because when checking sc.hasNext(), java is waiting user to type some input in console. Currently what I can do is open an thread for Udp client. If I change the order,

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

It doesn't make sense, since receive() will keep waiting util receive something, it will never read from system.in concurrently.

So how can i achieve my requirement without using a thread?

Inspired by @Andriy Kryvtsun's answer, i did a quick test As he said, this is somehow using non-blocking read, and keep letting socket timeout, to emulate

        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) {

        }
    }

Solution

  • Use unblocking method call InputStream#available() to get info if something ready for reading before using blocking Scanner#hasNext() call.

    Also you can call DatagramSocket#setSoTimeout(int timeout) before call blocking receive(DatagramPacket p) method. Thus you can break infinity waiting inside receive method after timeout period emulating unblocking reading.