Java 中断线程';优雅地';而在主回路中
假设我有以下代码:Java 中断线程';优雅地';而在主回路中,java,multithreading,concurrency,Java,Multithreading,Concurrency,假设我有以下代码: public void run(){ while (true){ function1(); ... functionN(); } } 我想“优雅地”退出——这意味着,一旦我发送了一个关闭信号,当前线程位于functionK(),线程将“中断”循环并退出运行 所以我试着使用Thread.interrupt()如下: public void run(){ while (true){ try {
public void run(){
while (true){
function1();
...
functionN();
}
}
我想“优雅地”退出——这意味着,一旦我发送了一个关闭信号,当前线程位于functionK(),线程将“中断”循环并退出运行
所以我试着使用Thread.interrupt()如下:
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可能会很昂贵(特别是因为应用程序在大多数情况下运行平稳)
我想知道是否有一种特殊的机制可以用于解决此类问题。对此非常清楚:
如果该线程在调用对象类的wait()、wait(long)或wait(long,int)方法时被阻塞,或者在调用该类的join()、join(long)、join(long,int)、sleep(long)或sleep(long,int)方法时被阻塞,那么它的中断状态将被清除,并接收到InterruptedException
如果在中断通道上的I/O操作中阻塞了此线程,则通道将关闭,线程的中断状态将被设置,线程将收到ClosedByInterruptException
如果该线程在选择器中被阻塞,那么该线程的中断状态将被设置,并且它将立即从选择操作返回,可能带有非零值,就像调用了选择器的唤醒方法一样
如果前面的条件都不成立,那么将设置该线程的中断状态
因此,如果您正在等待对象监视器,则只能依赖此异常。某些I/O操作引发了几个其他异常,但是如果您也不使用它们,那么除了检查interrupted()
标志外,没有其他选项
不过,您可以做的是重新组织代码:如果您有一个接一个地调用的N
方法,是否不可能将它们抽象成一个循环?通常可以找到一种重构代码以支持中断的方法,具体方法取决于您的实际场景。我的第一个问题是:为什么一个方法运行几分钟?这听起来有点可疑(尽管这可能是合理的)
不管怎样,中断性不是免费的,如果您希望代码比主循环的长度更能响应中断,您必须主动设计中断点
不过还有一件事:检查interrupted()
标志肯定不会花费太多的钱。当您在主循环中花费数分钟时就不会这样了,而且这比构造和处理异常要便宜得多。我甚至可以说,您会发现,几乎没有什么事情比调用线程.isInterrupted()
更快了,这一点非常清楚:
如果该线程在调用对象类的wait()、wait(long)或wait(long,int)方法时被阻塞,或者在调用该类的join()、join(long)、join(long,int)、sleep(long)或sleep(long,int)方法时被阻塞,那么它的中断状态将被清除,并接收到InterruptedException
如果在中断通道上的I/O操作中阻塞了此线程,则通道将关闭,线程的中断状态将被设置,线程将收到ClosedByInterruptException
如果该线程在选择器中被阻塞,那么该线程的中断状态将被设置,并且它将立即从选择操作返回,可能带有非零值,就像调用了选择器的唤醒方法一样
如果前面的条件都不成立,那么将设置该线程的中断状态
因此,如果您正在等待对象监视器,则只能依赖此异常。某些I/O操作引发了几个其他异常,但是如果您也不使用它们,那么除了检查interrupted()
标志外,没有其他选项
不过,您可以做的是重新组织代码:如果您有一个接一个地调用的N
方法,是否不可能将它们抽象成一个循环?通常可以找到一种重构代码以支持中断的方法,具体方法取决于您的实际场景。我的第一个问题是:为什么一个方法运行几分钟?这听起来有点可疑(尽管这可能是合理的)
无论哪种方式,可中断性都不是免费的,如果您希望代码对中断的响应比主循环的长度更快,那么必须积极设计中断点
不过还有一件事:检查
interrupted()
标志肯定不会花费太多的钱。当您在主循环中花费数分钟时就不会这样了,而且这比构造和处理异常要便宜得多。我甚至可以说,你会发现很少有比调用Thread.isInterrupted()
更快的事情了。你的第二个例子会在中断后继续循环。这是因为InterruptedException
实际上并不意味着设置了线程的中断标志;事实上,你根本不需要检查它
要解决此问题,您只需重新中断线程(让调用方知道线程已中断),然后中断:
public void run(){
while (true) {
try {
function1();
//...
functionN();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
break;
}
}
}
您的第二个示例将在中断后继续循环。这是因为
InterruptedException
实际上并不意味着设置了线程的中断标志;事实上,你根本不需要检查它
要解决此问题,您只需重新中断线程(让调用方知道线程已中断),然后中断:
public void run(){
while (true) {
try {
function1();
//...
functionN();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
break;
}
}
}
实际上,如果你在做CPU