How can you programatically cancel reading from an InputStream?
I've looked around StackOverflow and with Google and was unable to find a solution to my problem, so here's what I'm doing.
I have a Server for a Console application, and users connect to it with any Telnet Client. I'm handling Clients with three separate threads, one thread (ClientThread) controls all Program access to a Client, the ClientThread maintains two threads, one for processing input and one for sending output. The ClienThread reads the client socket and sends the input (if any) to the ProcessingThread whic开发者_如何学JAVAh processes the input and performs the actions the user dictated. The output Thread manages a queue of output that needs to be sent and sends it each time it wakes up. When a user disconnects I occasionally use Output that's left in the Output "queue" before the connection is terminated so I wanted to set it up so that the connection was kept alive until the Output Queue is empty - however the Thread that reads the socket (and ultimately closes it when there is no more output) is hanging on the read and I'm unable to close it. This wasn't a problem before when, upon the user disconnecting, I just closed the Socket. I'll give you the relevant code.
public class ClientThread extends Thread {
// Initialization and other code not pertaining to the problem
public void run() {
while (connected) {
try {
String input = in.readLine();
if (input != null) {
processor.queue(TextUtility.processBackspaceChars(input));
timeoutTimer.interrupt();
}
} catch (Exception e) {
if (e.getMessage() != null && !(e.getMessage().equals("socket closed")))
server.appendError("Issue reading from client: "
+ getClientDisplayInfo() + "\n"
+ "&r-The issue is:&w- " + e.getMessage() + "&r-.");
}
}
while (disconnecting) {
try {
if (outputThread.hasOutput()) {
sleep(10);
} else {
disconnecting = false;
outputThread.disconnect();
client.close();
}
} catch (Exception exc) {
server.appendError("Failed to close the Thread for client: " + getClientDisplayInfo());
}
}
}
public void disconnect() {
try {
connected = false;
disconnecting = true;
processor.disconnect();
timeoutTimer.disconnect();
in.close(); // This is the BufferedReader that reads the Socket Input Stream
this.interrupt(); // This was my attempt to break out of the read, but it failed
} catch (Exception e) {
server.appendError("Failed to close the Thread for client: "
+ getClientDisplayInfo());
}
}
}
I'm just curious how I can cancel the read without closing the Socket since I need to continue sending output.
I guess it is similar to the problems I faced yesterday You could invoke is.available()
on your input stream and check whether data is available before doing a (blocking) read.
Don't call available(): either you waste CPU calling it too frequently, or you waste time not calling it frequently enough, so your reponse times suffer. Set a read timeout on the Socket and have the reader thread check a 'cancel' flag every time it trips; set the flag from whereever you want to set it from.
精彩评论