Reputation: 41
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
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
Reputation: 5988
Look into CSP programming and BlockingQueue
s. 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