这是一个线程,处理来自服务器端的输入和输出:
public void run() {
Thread currentThread = Thread.currentThread();
while (!currentThread.isInterrupted()) {
SocketChannel socketChannel = null;
try {
socketChannel = serverSocketChannel.accept();
readFromSocket(socketChannel);
} catch (ClosedByInterruptException e) {
// closed due to interrupt
connected = false;
} catch (IOException e) {
if (!isInterrupted()) {
e.printStackTrace();
}
connected = false;
} finally {
quietClose(socketChannel);
}
}
}
/**
* Reads an message from socketChannel and executes
* {@link AbstractServer#handleMessage(String)}. Initializes
* {@link #writer} with the socketChannel.
*
* @param socketChannel
* @throws IOException
*/
public void readFromSocket(SocketChannel socketChannel) throws IOException {
reader = null;
writer = null;
try {
reader = new BufferedReader(new InputStreamReader(socketChannel.socket().getInputStream()));
if (writer == null) {
writer = new PrintWriter(socketChannel.socket().getOutputStream(), true);
}
String message;
while ((message = reader.readLine()) != null) {
handleMessage(message);
}
} catch (ClosedByInterruptException e) {
throw e;
} catch (IOException e) {
e.printStackTrace();
} finally {
quietClose(reader);
quietClose(writer);
}
}
如果我调用print方法,线程被卡住了。这意味着"before"被打印出来了,但"after"却从未出现过。打印机的CheckError方法返回false!
/**
* Sends a message to the client.
*
* @param message
*/
public void sendMessage(final String message) {
System.out.println("before");
writer.print(message);
System.out.println("after");
writer.flush();
}
它在一个AbstractServer中,由两个不同的服务器使用。第一个之前已经使用过,并且总是没有问题(现在仍然如此)。另一个是新的,导致了这个问题。对于每个初始化的连接(两个具有不同端口的本地主机),绝对只有一个写入器。
客户端Datafetcher看起来像这样:
protected void fetchDataFromSocket() {
if (socketDataFetcher != null) {
socketDataFetcher.interrupt();
}
socketDataFetcher = new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
String message = socketConnection.readLine();
if (messageHandler != null) {
messageHandler.handleMessage(message);
}
} catch (IOException e) {
Thread.currentThread().interrupt();
}
}
}
});
socketDataFetcher.start();
}
它也和另一个几乎一样,只有很小的变化,实际上不会引起问题。是什么原因导致印刷工人这样做呢?
编辑:如果我不启动socketDataFetcher在客户端,打印机不会被卡住!
虽然我没有看到声明,但reader和writer对象(在readFromSocket()方法中引用)看起来可能是成员变量。我会担心读写器不是线程安全的。我会看看关于删除这些成员变量,看看你是否仍然有问题的作家。