因此,我整整一天都在为此问题苦苦挣扎,并且查阅了一些线程教程和示例仍未能达到我想要的结果.
我有一个线程,其唯一的工作是轮询Strings的LinkedBlockingQueue,然后使用PrintWriter通过套接字将字符串传递给客户端.该功能运行良好,但是我现在尝试通过允许它在连接中断和重启时正常失败来增强它.为了完成此任务,我在线程上调用中断,然后加入线程,最终目的是重新创建Thread对象.不幸的是,线程挂起了join的调用,这必须意味着线程实际上从未成功死亡,但是我对为什么会这样感到困惑.下面的相关代码.
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)循环,该循环应始终循环并检查线程是否已被中断,在这种情况下,它会抛出在底部捕获的异常以使线程死亡.我认为PrintWriter不应阻止代码的执行.任何帮助将非常感激.
解决方法:
JVM不会强制中断来终止线程.您需要确保代码调用的所有阻塞调用都支持中断.
例如,如果客户端未接收到数据,则输出缓冲区将填满,并且toClient.println()将阻塞,但是此调用不支持中断,因此调用.interrupt()不会终止它.
我建议添加更多调试日志,以确定确切的代码块在哪里.