2

我试图找出一些行为。我有一些产生一个线程的代码。它等待一段时间,然后中断它,加入它,然后退出该方法。

.
.
.
try {
        Thread.sleep(processForMillis);
    }
    catch (InterruptedException ex) {
        // Won't happen, ignore.
    }

    for (Thread t : threads) {
        logger.debug("Interrupting Thread " + t.getName());
        t.interrupt();
    }

    for (Thread t : threads) {
        try {
            t.join(1000L);
            logger.debug("Joined Thread " + t.getName());
            logger.debug("isAlive? " + t.isAlive());
        }
        catch (InterruptedException ex) {
            // this will never happen
            logger.debug("InterruptionException while joining, but didn't expect it.");
        }
    }
} // end of method

我目前只用一个线程运行它。我可以在我的日志中看到,通常 isAlive() 在加入后会为假,但有时它仍然存在。线程处于一个while循环中:

while(!Thread.currentThread().isInterrupted()){
.
// do some blocking io stuff here
}

所以我怀疑正在发生的事情是我们在读取/处理输入流(阻塞io)时中断了线程,并且它所花费的时间超过了达到while条件并完成连接所需的时间。

所以我的问题是,线程会发生什么?

它不再被引用,线程可以被垃圾收集,但没有一个资源被正确清理,这看起来很糟糕。除了切换到 NIO 之外,还有更好的模式吗?

4

2 回答 2

1

interrupt() 只是在它已被中断的线程上设置一个标志。发生这种情况时,许多阻塞调用不会解除阻塞,这意味着线程几乎不受中断的影响并继续做它的事情(例如阻塞 InputStream)。

我猜在某些情况下,线程不会在给定的连接超时(此处为 1 秒)内解除阻塞并达到您的 while 条件,在其他情况下,阻塞调用恰好在超时内完成并且线程结束。

只要一个线程正在运行,它仍然会有一个引用并且不会被垃圾收集。如果阻塞调用永远不会解除阻塞 - 如果它从例如另一端已静默消失的死 tcp 套接字读取,则可能发生这种情况,线程可能永远不会结束。

于 2010-01-29T16:39:59.803 回答
0

除了 nos 的答案,要中断阻塞 IO 调用,您可以使用close()它的流

于 2010-01-29T16:51:33.587 回答