当我中断线程时,有什么办法可以在睡眠后执行立即语句

时间:2012-10-07 16:41:21

标签: java multithreading

使用评论查看以下代码段:

try {
  Thread.sleep(20000); // Foo thread sleeps for 20 seconds
  System.out.println("After the sleep statement");
} catch(Exception exc) {
    exc.printStackTrace();
  }

// It has been 12 seconds since the thread went to sleep and....I interrupt

Foo.interrupt(); // exception gets thrown and the code in the catch block gets executed

有什么办法可以在sleep语句之后执行下一个语句?我想在某个时候唤醒线程并希望它继续工作。对此有什么想法/方法吗?

3 个答案:

答案 0 :(得分:1)

不确定这是否是你想要的?

try {
  Thread.sleep(20000); // Foo thread sleeps for 20 seconds
  System.out.println("After the sleep statement");
} catch(InterruptedException exc) {
    System.out.println("Sleep was interrupted");
} catch(Exception exc) {
    exc.printStackTrace();
}

sleep()在被中断时抛出InterruptedException。因此"Sleep was interrupted"将打印在interrupt()上,而"After the sleep statement"仅在sleep()设置为睡眠配置20秒后才会被调用。

如果您不关心sleep()是否正常返回或抛出并继续工作,请用空try-catch包裹它:

public void interruptibleSleep(long millis) {
    try {
      Thread.sleep(millis);
    } catch(InterruptedException exc) {}
}

然后代替Thread.sleep(20000)致电interruptibleSleep(20000)

interruptibleSleep(20000);
System.out.println("After the sleep statement");

答案 1 :(得分:1)

我觉得你很困惑。这是发生的事情

public void run() { 
  // This executes as soon as the thread is run
  try {
     // We decide to sleep for UPTO 20 seconds
     Thread.sleep(20000); 

     // Code here executes ONLY if we managed to sleep for 20 seconds without 
     // interruption

  } catch(InterruptedException exc) {
     // Code here executes ONLY if we were interrupted
  } catch(Exception exc) {
     // This shouldn't ever execute in theory
  }

  // Code here ALWAYS executes after the sleeping (and ONE of the two blocks) 
  // whether or not it was interrupted.
}

答案 2 :(得分:1)

The Java Tutorials

上有一段非常好的段落
  

中断是一个线程的指示,它应该停止它正在做的事情并做其他事情。由程序员决定线程如何响应中断,但线程终止是很常见的。这是本课中强调的用法。

可靠地停止和启动线程是设计并发应用程序的重要部分。即使你可以重新利用中断来做任何你想做的事情,如果你为了它最常见的目的而留下中断,你的代码将更可靠,更容易维护 - 请求线程退出。如果用户在20秒超时完成之前决定关闭应用程序,那么您可能希望这样做。

那么如何解决原始问题 - 允许一个线程向另一个线程表明是时候开始工作了。下面的类显示了如何使用CountDownLatch来解决此问题。

新的Foo:

class Foo extends Thread
{

   CountDownLatch latch = new CountDownLatch(1);

   @Override
   public void run()
   {
      try
      {
         boolean early = latch.await(20, TimeUnit.SECONDS);
         System.out.println("Doing work " + (early ? "right away" : "after delay"));
         // do real work here...
      }
      catch (InterruptedException e)
      {
         System.out.println("Interrupt detected. Exiting thread...");
      }
   }

   public void goAhead()
   {
      latch.countDown();
   }
}

我们摆脱了“Sleep”并用对latch对象的await方法的调用替换它。要使foo工作,请调用:

foo.goAhead();  // prints out "Doing work right away"

这会导致闩锁倒计时。对“await”的调用将立即退出而不抛出异常并返回true。

要关闭foo,请使用:

foo.interrupt();  // prints out "Interrupt detected..."

这将导致等待抛出InterruptedException,就像睡眠一样。

或什么也不做。等待20秒后超时的调用,不会抛出异常并返回false。 Foo打印出“延迟后做工作”

这种设计的一个长期优势是,当您“正在工作”时,您可能需要调用其他阻止方法。中断仍可用于中断其中任何一个,并帮助您可靠地关闭线程以响应意外事件。