Java线程中断和join(join后线程还活着)
我正在尝试找出一些行为。我有一些生成一个线程的代码。它等待一段时间,然后中断它,加入它,然后退出该方法。
.
.
.
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() 在连接后将为 false,但有时它仍然处于活动状态。线程处于 while 循环中:
while(!Thread.currentThread().isInterrupted()){
.
// do some blocking io stuff here
}
所以我怀疑正在发生的事情是我们在线程读取/处理输入流(阻塞 io)时中断线程,并且它花费的时间超过了达到 while 条件并完成所需的时间加入。
所以我的问题是,线程会发生什么?
它不再被引用,并且线程可以被垃圾收集,但是没有任何资源被正确清理,这看起来很糟糕。除了切换到 NIO 之外,还有更好的模式吗?
I'm trying to figure out some behavior. I've got some code that spawns one thread. It waits some amount of time, and then interrupts it, joins it and then exits the method.
.
.
.
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
I am currently running this with just one thread. I can see in my logs that usually, isAlive() will be false after the join, but sometimes it is still alive. The thread is sitting in a while loop:
while(!Thread.currentThread().isInterrupted()){
.
// do some blocking io stuff here
}
So what I suspect is happening is we are interrupting the thread while it is reading/processing the inputstream (blocking io) and it is taking more than the time it takes to hit the while conditional and finish the join.
So my question is, what happens to the thread?
It is no longer referenced and the thread can be garbage collected, but none of of the resources are cleaned up properly, and that seems bad. Is there a better pattern for this besides switching to NIO?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Interrupt() 只是在线程上设置一个标志,表明它已被中断。发生这种情况时,许多阻塞调用不会解除阻塞,这意味着线程几乎不受中断影响,并继续执行其操作(例如在输入流上阻塞)。
我猜测在某些情况下,线程不会在给定的连接超时(此处为 1 秒)内解锁并达到 while 条件,在其他情况下,阻塞调用恰好在超时内完成并且线程结束。
只要线程正在运行,它仍然会有一个引用并且不会被垃圾收集。
如果阻塞调用永远不会解除阻塞(如果它从另一端已悄然消失的死 TCP 套接字读取数据,则可能会发生这种情况),则线程可能永远不会结束。
interrupt() just sets a flag on the thread that it has been interrupted. Many blocking calls does not unblock when this occurs, meaning the thread is pretty much unaffected by the interrupt and keeps doing its thing(e.g. blocking on an InputStream).
I'm guessing in some cases the thread doesn't unblock and hit your while condition in the given join timeout (1 second here), in other cases the blocking call happens to complete within the timeout and the thread ends.
As long as a thread is running it will still have a reference and not be garbage collected.
If the blocking call never unblocks - which could happen if it reads from e.g. a dead tcp sockets whos other end has silently disappeard, the thread might never end.
除了 nos 的答案之外,要中断阻塞 IO 调用,您可以
close()
它的流In addition to the nos's answer, to interrupt a blocking IO call you can
close()
its stream