Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 中断线程';优雅地';而在主回路中_Java_Multithreading_Concurrency - Fatal编程技术网

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