java在主循环中“优雅地”中断线程
假设我有以下代码:
public void run(){
while (true){
function1();
...
functionN();
}
}
我想“优雅地”退出——这意味着一旦我发送了一个关闭信号,当前线程位于functionK(),线程就会“中断”循环并退出运行
所以我试着使用线程。中断()如下:
public void run(){
while (true){
try {
function1();
...
functionN();
} catch (InterruptedException ex) {
/* Cleanup and exit. */
}
}
}
但这不起作用——即使在中断标志打开的情况下,线程也会继续无休止地运行
记录在案:
public void run(){
while (!thread.isInterrupted()){
try {
function1();
...
functionN();
} catch (InterruptedException ex) {
/* Cleanup and exit. */
}
}
}
停止循环,但对我没有帮助。由于每个函数所做的事情可能需要几分钟,而且有很多不同的函数,因此在每个函数之前检查中断标志是否为1可能代价高昂(特别是因为应用程序在大多数情况下运行平稳)
我想知道是否有一种特殊的机制可以用来解决这种问题
# 1 楼答案
您的第二个示例将在中断后继续循环。这是因为
InterruptedException
实际上并不意味着设置了线程的中断标志;事实上,你根本不需要检查它要解决这个问题,只需重新中断线程(让调用方知道线程被中断),然后中断:
# 2 楼答案
关于这一点API documentation非常清楚:
因此,只有在等待对象监视器时,才能依赖此异常。某些I/O操作引发了几个其他异常,但是如果您也不使用它们,那么除了检查
interrupted()
标志外,没有其他选项不过,您可以做的是重新组织代码:如果有
N
方法被一个接一个地调用,那么不可能将它们抽象成一个循环吗?通常情况下,可以找到一种重构代码以支持中断的方法,具体方法取决于您的实际场景。我的第一个问题是:为什么一个方法要运行几分钟?这听起来有点可疑(尽管这可能是合理的)不管怎样,可中断性都不是免费的,如果希望代码对中断的响应比主循环的长度更灵敏,就必须积极地设计中断点
不过,还有一件事:检查
interrupted()
标志绝对是不昂贵的。当您在主循环中花费数分钟时就不会了,而且这比构造和处理异常要便宜得多。我甚至可以说,你会发现几乎没有什么事情比打电话给Thread.isInterrupted()
更快# 3 楼答案
实际上,如果您在方法中执行CPU限制的工作,您必须自己检查
Thread.interrupted()
,然后自己抛出InterruptedException
。Java不会神奇地为你做到这一点,除非你把车停在一些特别设计的空间,比如Semaphore.wait()
等# 4 楼答案
正如《实践中的Java并发》一书中所述:“Java没有提供任何机制来安全地强制线程停止正在做的事情”,因此您必须在自己这方面实现一些东西。检查中断标志并处理InterruptedException是管理线程取消的最佳方法。 如果你们中的一个函数1()。。。函数No()位于数据库事务的中间,或者HTTP调用由您的程序来处理取消;您可以等待到n秒并保存当前状态,或者取消事务并返回,要执行的操作由应用程序逻辑决定