2014-05-07 121 views
0

由于某些原因,在迭代线程列表并中断所有线程时,它们都不会执行带有InterruptedException的catch块。线程中断()不会中断线程

在下面的库:https://github.com/ranisalt/LiuThread

我有两个线程,他们每个人都有执行服务,其中一人持有的读者,另一个读作家。作家应该每100毫秒产卵一次,写入缓冲区并退出/停止/不管再次写入什么。读者有4条线索试图阅读,如果可以的话,他们也应该放弃,所以有空间供其他读者阅读。

我有每个100(读者和作家),如果他们无法读取或写入,他们等待60秒。

然后,我有一个协调器线程,在缓冲区为空(并中断作者)或全部(中断读者)的情况下继续测试,所以他们永远不应该等待60秒。缓冲区知道它的状态。

的问题是,由于某种原因,这个片段:

for (ThreadAzul azul : threadsAzuis) { 
    azul.interrupt(); 
} 

不中断线程!我已经使用println来查看是否被中断:

try { 
    sleep(60000); 
    System.out.println(this.getName() + " foi dormir"); 
} catch (InterruptedException e) { 
    System.out.println(this.getName() + " foi interrompido"); 
} 

但是,这从来没有被写入。 interrupt()没有使catch块执行的原因是什么?

+0

我在过去在线程中使用'System.out.println()'进行调试时也遇到过问题,可能是并发性和冲突问题?在System.out.println(this.getName()+“foi interrompido”)之后尝试'System.out.flush()';' – morgano

+0

@morgano这不是问题,它们正确地睡眠,但睡眠不被打断。 – ranisalt

回答

4

里面的main方法你在你的Thread调用run()所以你永远不会开始一个新的Thread而是初始main线程中运行其代码。因此,在您从未启动的Thread实例上调用interrupt将不会中断正在执行代码的main线程。

当您将submit a Thread实例复制到Executor时,同样的错误会重复。因为Thread实现Runnable执行人将执行Thread实例的run方法,但Executor将这样做在它自己的管理Thread而不是由实例所表示的Thread内已创建但从未启动。

所以再次调用interrupt您从未启动的Thread实例将不会中断实际执行代码的线程。

一般你应该不要混合ThreadExecutor的用法。决定一种方式,手动处理Thread或使用ExecutorSevice s。

而当您使用Thread时,您必须使用start()方法启动它们,而不是调用run()方法。

1

在可中断操作期间线程只会被中断,例如Thread.sleep(),Thread.wait(),和一些I/O调用(不是全部)。

+0

是的,我想中断睡眠线程。这个“缓冲区”实际上只是协调器控制的一个单独对象。 – ranisalt

+0

@EJP,技术上并非如此:线程可以在_any_时间中断。当它被中断时,它会设置一个标志(总是),并且它会抛出一个InterruptedException _iff_它被阻塞在一个类似等待的方法调用中。如果要使用中断来获得长时间运行的线程的注意力,那么该线程必须定期检查该标志。异常的目的只是为了给线程一个_chance_来检查标志,如果它恰好在当时正在睡觉。 –

0

设置中断标志不会中断线程。线程只在检查时才结束,是否应该结束。因此,请给线程机会检查isInterrupted(),或在睡眠或等待时中断它。 如果您在运行()中断()将不起作用的长期方法。您必须实施定期检查或其他解决方法。