中断/杀死正在运行的线程

时间:2011-12-23 11:17:52

标签: java multithreading

在发生特定超时时,我需要杀死/取消/中断/失败正在运行的线程。我使用ExecutorService来管理线程池,通过它我可以使用Future的cancel()方法取消任务,该方法从ExecutorService的视图中删除它,但线程本身继续运行。

在线查看,人们talk about interrupting threads使用isInterrupted()方法进行循环或等待IO,可以通过显示InterruptedException来处理。

杀死没有循环(或有任何其他挂钩)并且没有等待IO的线程的一般做法是什么?环顾四周,Thread.stop()似乎做了我需要的东西(只是盲目杀死线程),但不建议使用它。

3 个答案:

答案 0 :(得分:3)

如果您使用ExecutorService,那么您不应该乱用它的线程:这个概念隐藏在执行程序后面,这是一个比线程更高级别的概念,因此不提供管理它们的方法。我强烈建议你停止整个Executor而不是试图阻止它的一个线程。

请注意ExecutorService中的线程正在循环,其循环包括等待任务在其任务队列中可用。

Java中没有简单的方法来阻止没有循环的线程,你可以做的是:

  • 有一个易失性布尔标志,线程的Runnable会检查它是否应该停止(可以用作线程循环中的条件的相同标志)。
  • 调用Thread.interrupt()尝试(尽力而为,如果您不知道自己在做什么,则非常不安全)停止与同步相关的等待/锁定/获取/ ...线程陷入困境。

答案 1 :(得分:1)

我个人建议你去中断路线,因为它是最干净的方式和结束该线程的优雅方式。

让我们试着很好地定义我们的目标。一个线程只是一个单独的进程,可以执行一组您指定要执行的任务。可能您必须在代码中找到可中断点,并且必须在这些点上进行中断()检查。显然,这些要点应该达到逻辑结局。

例如,

public void run(){
      if (Thread.currentThread().interrupted()) {
           return;
      }
      //LogicA start
      //LogicA end
      if (Thread.currentThread().interrupted()) {
           return;
      }
      //LogicB start
      //LogicB end
      if (Thread.currentThread().interrupted()) {
           return;
      }
      //LogicLong start
      //Long code here cannot end or exit or kill the thread now. Let it finish
      //LogicLong ends
      if (Thread.currentThread().interrupted()) {
           return;
      }
      //LogicD start
      //LogicD end
}

答案 2 :(得分:1)

如果你已经Executorservice,那么你已经收到了Future。因此,取消作业的唯一合理且干净的方法是调用future.cancel(boolean mayInterruptIfRunning)。如果作业当前正在运行,则设置mayInterruptIfRunning将中断作业,如果作业未运行,则不执行任何操作。因此,您只需要通过偶尔检查Thread.interrupted()来编写工作以尊重中断。

请注意作业线程之间的区别。您提交作业,因此您不应该通过试图绕过可能根本没有被逗乐的ExecutorService来解决线程。致电Future.cancel(true),您可以向所有相关方发出干净的信号。