2010-01-29 28 views
2

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

. 
. 
. 
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 
} 

所以我怀疑正在发生的事情,而在读取/处理的InputStream(阻塞IO)是我们中断线程,它正在采取比它花费的时间更多打条件并完成连接。

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

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

回答

1

interrupt()只是在线程中设置了一个中断标志。当发生这种情况时,许多阻塞调用都不会解除阻塞,这意味着线程几乎不受中断的影响,并继续执行其操作(例如,阻塞InputStream)。

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

只要一个线程正在运行,它仍然会有一个引用而不是垃圾收集。 如果阻止呼叫不会解除阻止 - 如果从阻止呼叫中读取,则可能发生这种情况。一个死的tcp套接字谁的另一端已悄然消失,该线程可能永远不会结束。

+0

是啊,这就是我怀疑。除了NIO或增加(或不使用)加入等待时间,是否有一个很好的模式来解决这个问题? – DanInDC 2010-01-29 16:46:24

0

除号的回答,来中断阻塞的IO叫你可以close()其流