【问题标题】:Resume interrupted thread恢复中断的线程
【发布时间】:2014-05-21 04:22:07
【问题描述】:

我想恢复中断线程的工作,请告诉我一些可能的解决方案。

class RunnableDemo implements Runnable 
{

   public void run() 
   {
    while(thread.isInterrupted())
        {
        try{}
                catch(Exception e){ //exception caught}
        }

   }

}

如果捕获到异常,线程会被中断,但是即使捕获到异常,我也希望线程继续工作,所以请给我一些解决这个问题的方法。

提前致谢

【问题讨论】:

  • 捕捉到异常时会继续while(true) { try { doSomething(); } catch(Exception e) {} }

标签: java multithreading


【解决方案1】:

线程中断是您在编写线程时选择遵守的。因此,如果您不希望线程被中断,请不要检查中断状态并继续。

您需要 try/catch 语句(关于线程中断)的唯一情况是调用抛出 InterruptedException 的阻塞方法时。然后,您需要避免让该异常停止线程的工作。

当然……你应该考虑一下这是否是一种合适的行为方式。线程中断是一件很有帮助的事情,选择不遵守它可能会让您的代码用户感到烦恼。

【讨论】:

    【解决方案2】:

    只有当有人调用该线程的 interrupt() 方法时,线程才会被中断,而不是因为在运行线程时抛出了其他随机异常,正如您所想的那样。

    当线程的interrupted()方法被调用时,如果线程处于阻塞操作的中间(例如IO读取),会在线程中抛出InterruptedException。

    当抛出 InterruptedException 时,您应该知道中断状态已被清除,因此下次您在线程中调用 isInterrupted() 时会返回 false(即使您只是注意 InterruptedException)

    在编写线程时请记住这一点。如果您不明白我在说什么,请停止编写多线程代码并阅读一些有关 Java 并发的书籍。

    【讨论】:

    • “在阻塞操作的中间(例如 IO 读取)” - 遗憾的是,这是不正确的。通常,阻塞操作,尤其是(大多数)IO操作,是不可可中断的。
    • 是的,New IO (NIO) 包中个可中断的 IO 操作,就像 Selectors 和 interruptible上的操作一样> 频道。然而,Java 的标准 IO(基于Stream)是不可中断的,网络Sockets 上的非通道操作也不是,例如connect()。进入synchronized 块时被阻止的代码也不可中断。我的观点是:IO 域中的大多数“阻塞操作”是不可中断的,除了那些专门设计的并且通常需要程序员明确选择的操作。
    【解决方案3】:

    一个警告:如果您的线程在调用第三方库时处理了一个 InterruptedException,那么您不一定知道该库是如何对它做出反应的(即,它是否让库对象在让您的程序继续使用它们有意义吗?)

    一些开发人员(包括一些库开发人员)错误地认为中断意味着“关闭程序”,他们所担心的只是关闭文件等;并没有太多关于图书馆是否可以继续使用的问题。

    试试看,但如果您正在编写代码来控制航天器或核反应堆或其他东西,那么您可能需要做一些额外的工作来真正了解库的作用。

    【讨论】:

      【解决方案4】:

      我已经编写了一个可重用的代码来获得此功能,其中线程可以暂停和恢复。请在下面找到代码。您可以扩展 PausableTask 并覆盖 task() 方法:

      public abstract class PausableTask implements  Runnable{
      
          private ExecutorService executor = Executors.newSingleThreadExecutor();
          private Future<?> publisher;
          protected volatile int counter;
          private void someJob() {
              System.out.println("Job Done :- " + counter);
      
          }
      
          abstract void task();
      
          @Override
          public void run() {
              while(!Thread.currentThread().interrupted()){
                  task();
              }
          }
      
          public void start(){
              publisher = executor.submit(this);
          }
      
          public void pause() {
              publisher.cancel(true);
          }
      
          public void resume() {
              start();
          }
      
          public void stop() {
              executor.shutdownNow();
          }
      }
      

      希望这会有所帮助。有关更多详细信息,请查看此链接或在评论部分给我留言。 http://handling-thread.blogspot.co.uk/2012/05/pause-and-resume-thread.html

      【讨论】:

      • 我对 Java 还很陌生,对 Future 完全不熟悉,但我认为这正是我想要做的。你能解释一下它和使用 myThread.join() 和 .start() 的区别吗?
      【解决方案5】:

      正如其他人已经说过的,通常中断是取消任务的正确方法。如果你真的需要实现一个不可取消的任务,至少要确保在你完成不可中断的工作后恢复线程的中断状态:

      public void run() {
          boolean interrupted = false;
          try {
              while (true) {
                  try {
                      callInterruptibleMethod();
                  } catch (InterruptedException ex) {
                      interrupted = true;
                      // fall through and retry
                  }
              }
          } finally {
              if (interrupted) {
                  // restore interruption state
                  Thread.currentThread().interrupt();
              }
          }
      }
      

      (来自书籍:Java Concurrency in Practice

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-03
        • 1970-01-01
        • 2011-11-10
        • 1970-01-01
        相关资源
        最近更新 更多