所以我一直在努力解决这个问题一整天,并且咨询了一些线程教程和示例仍然无法达到我想要的结果。
我有一个Thread,其唯一的工作是轮询String的LinkedBlockingQueue,然后使用PrintWriter将套接字通过套接字传递给客户端。该功能工作正常,但我现在正试图通过允许它在连接中断和重新启动时正常失败来增强它。为了实现这一点,我在线程上调用中断,然后加入,最终目标是重新创建Thread对象以重新开始。不幸的是,线程挂起了连接的调用,这必然意味着线程从未真正设法死亡,但我完全不知道为什么会这样。相关代码如下。
try {
resultSetStreamer.interrupt();
resultSetStreamer.join();
logger.info("Streamer finished.");
} catch (InterruptedException e) {}
实际线程代码;
class ResultSetStreamer implements Runnable {
GZIPOutputStream gzos = null;
Socket clientSocket = null;
@Override
public void run() {
try {
logger.debug("Thread started.");
// Blocks and waits for an external connection.
clientSocket = serverSocket.accept();
// Creates a compression stream using best possible compression
// to the external connection.
gzos = new GZIPOutputStream(clientSocket.getOutputStream()) {
{
def.setLevel(compression);
}
};
PrintWriter toClient = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(gzos), bufferSize), false);
while (true) {
if (Thread.interrupted()) {
throw new InterruptedException();
}
if (moreRowsToReceive || !dataBuffer.isEmpty()) {
// Synchronisation point.
String row = dataBuffer.poll(pollTime,
TimeUnit.MILLISECONDS);
if (row != null) {
toClient.println(row);
logger.trace("Current row: " + ++currentCount + ".");
}
} else {
toClient.flush();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
try {
gzos.finish();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
logger.debug("Thread finished.");
}
}
要查看的主要位置是while(true)循环,它应该始终循环并检查Thread是否已被中断,在这种情况下,它会抛出在底部捕获的异常,以便允许Thread死。我不认为PrintWriter应该阻止代码的执行。任何帮助将不胜感激。
答案 0 :(得分:2)
JVM不会强制中断终止线程。您需要确保代码调用的所有阻塞调用都支持中断。
例如,如果客户端没有接收数据,输出缓冲区将填满并且toClient.println()将阻塞,但此调用不支持中断,因此调用.interrupt()不会终止它。
我建议添加更多调试日志以确定代码阻塞的确切位置。
答案 1 :(得分:1)
在您正在运行的计算机上,尝试启动jconsole并附加到正在运行的程序。在“线程”选项卡下,您应该能够单击每个线程并查看它当前正在执行的操作。这应该可以指示您的Runnable对象上的语句尚未完成。