Vincenzo Scotti
Vincenzo Scotti

Reputation: 41

Make thread skip read input operation from other thread

I have created 2 threads that works together for a socket connection: SocketIn and SocketOut (they are both working in a while(true) statement. In certain moments i need the SocketOut thread stop waiting for keyboard input a keep executing the following instructions even if he had read a null value and i need to do that without closing the thread or getting out the while(true). I have no idea on how to do that, so I need some advices.

Upvotes: 3

Views: 63

Answers (2)

Ivan Golovach
Ivan Golovach

Reputation: 209

You can introduce one more thread for reading keyboard. Then add some "channel" with rich features of interruption from keyboard reader to socket writer (for example some BlockingQueue):

class SocketApp {
    public static void main(String[] args) throws IOException {
        ExecutorService pool = Executors.newCachedThreadPool();

        URL url = new URL("http://...");
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("POST");
        con.setDoOutput(true);

        OutputStream dst = con.getOutputStream();
        InputStream src = con.getInputStream();

        // channel between keyboard reader and socket writer
        BlockingQueue<Integer> consoleToSocket = new ArrayBlockingQueue<>(256);

        // keyboard reader
        pool.submit(() -> {
            while (true) {
                consoleToSocket.put(System.in.read());
            }
        });

        // socket writer
        pool.submit(() -> {
            while (true) {
                dst.write(consoleToSocket.take());
            }
        });

        // socket reader
        pool.submit(() -> {
            while (true) {
                System.out.println(src.read());
            }
        });
    }
}

// Now you can use different features of BlockingQueue.
// 1. 'poll' with timeout
// socket sender
pool.submit(() -> {
    while (true) {
        Integer take = consoleToSocket.poll(3, TimeUnit.SECONDS);
        if (take != null) {
            dst.write(take);
        } else {
            // no data from keyboard in 3 seconds
        }
    }
});

// 2. Thread interruption
// socket sender
pool.submit(() -> {
    while (true) {
        try {
            Integer take = consoleToSocket.take();
            dst.write(take);
        } catch (InterruptedException e) {
            // somebody interrupt me wait for keyboard
        }
    }
});

Upvotes: 0

Fabian Zeindl
Fabian Zeindl

Reputation: 5988

Look into CSP programming and BlockingQueues. You could use a Queue in your loop that accepts "commands". One of the command is input from the socket, the other command is input from the keyboard.

private final BlockingQueue<Command> inputChannel = new SynchronousQueue<>();

public void run() {
    while (true) {
        Command request = this.inputChannel.take();

        if (request instanceof Command.KeyboardInput) {
            ...

        } else {
            ...
        }
    }
}

Upvotes: 1

Related Questions