1

请查看以下带有注释的代码段:

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 语句之后执行下一条语句?我想在某个时间唤醒线程并希望它继续工作。有什么想法/方法吗?

4

3 回答 3

1

The Java Tutorials中有一段措辞很好的段落

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

可靠地停止和启动线程是设计并发应用程序的重要部分。即使您可以重新利用中断来做任何您想做的事情,但如果您将中断用于最常见的目的——请求线程退出,那么您的代码将更可靠,更容易为其他人维护。如果用户决定在 20 秒超时结束之前关闭应用程序,这可能是您想要做的事情。

那么如何解决最初的问题——允许一个线程向另一个线程指示该开始工作了。下面的类显示了如何使用 CountDownLatch 来解决这个问题。

新福:

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..."

这将导致 await 像 sleep 一样抛出 InterruptedException。

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

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

于 2012-10-07T20:25:14.663 回答
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中断时抛出。因此,仅当管理睡眠配置为 20 秒时才会在调用时"Sleep was interrupted"打印。interrupt()"After the sleep statement"sleep()

如果您不在乎是sleep()正常返回还是抛出并继续工作,请用 empty 包装它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");
于 2012-10-07T16:43:27.350 回答
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.
}
于 2012-10-07T16:55:09.597 回答