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