这样的请求很重视,⽐如wait,sleep(阻塞⽅式),当它们接到中断请求时会抛出⼀个异
常,或者进⼊时中断状态就已经被设置了。所以这两个⽅法尽量不要⽤。
下例中在两处⽤到了检测中断技术,因为put是个阻塞操作,所以在之前检测总⽐在
之后检测性能更好。前提是此时没有消费者线程或是put是个很耗时的操作,像这种对中断
状态进⾏显式的检测会对调⽤可中断的阻塞⽅法时很有⽤外,因为通常我们不能得到期望的
响应。
中断策略
正如需要为任务制定取消策略⼀样,也应该定制线程中断策略。⼀个中断策略决定线
程如何应对中断请求--当发现中断请求时,它会做什么。
区分任务和线程对中断的反应是很重要的,任务不会在⾃⼰拥有的线程中执⾏,它们
借⽤属于服务的线程,⽐如线程池,如果代码并不是线程的所有者就应该⼩⼼地保存中断状
态(如果你给主⼈打扫房间,主⼈不在的这段时间你不能把收到的邮件全丢掉,应该收起来
待主⼈回来再处理)。这就是为什么⼤多数可阻塞的库函数,仅仅抛出
InterruptedException做为中断的响应,这也是最合理的策略。
在理中断时应该保存中断状态,也不能简单的是把InterruptedException传递给调⽤
者,应该在它之后恢复中断的状态:Thread.currentThread().interrupt();
当检查到中断请求时,任务不需要放弃所有的事情,可以选择推迟直到更合适的时
机。这需要记得它已经被请求过中断了,完成当前正在进⾏的任务,再抛出中断异常或指明
中断,这种技术可以保证数据结构不被破坏。
public class PrimeProducer extends Thread {
private final BlockingQueue<BigInteger> queue;
PrimeProducer(BlockingQueue<BigInteger> queue) {
this.queue = queue;
}
//这个例⼦可以很好的处理阻塞操作的中断问题,通过中断。
public void run() {
try {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted())
queue.put(p = p.nextProbablePrime());
} catch (InterruptedException consumed) {
/* Allow thread to exit */
}
}
public void cancel() {
interrupt();
}
}