3

因此,我已经为这个问题苦苦挣扎了一整天,并且在查阅了一些线程教程和示例后,仍然无法达到我想要的结果。

我有一个线程,其唯一的工作是轮询字符串的 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 应该阻止代码的执行。任何帮助将非常感激。

4

2 回答 2

2

JVM 不强制中断来终止线程。您需要确保您的代码调用的所有阻塞调用都支持中断。

例如,如果客户端没有接收数据,输出缓冲区将填满,toClient.println() 将阻塞,但此调用不支持中断,因此调用 .interrupt() 不会终止它。

我建议添加更多调试日志以确定代码块的确切位置。

于 2012-07-03T17:02:57.647 回答
1

在您正在运行的机器上,尝试启动 jconsole 并附加到您正在运行的程序。在“线程”选项卡下,您应该能够单击每个线程并查看它当前在做什么。这应该让您知道您的 Runnable 对象上的哪些语句尚未完成。

于 2012-07-03T18:42:01.517 回答