我正在阅读 《Java并发编程实践》,在章节“Cancellation and Shutdown”中提到:
一个任务不应假设它所执行的线程的中断策略,除非它明确地设计为在具有特定中断策略的服务中运行。无论任务将中断解释为取消还是采取其他一些动作,它都应当小心地保留执行线程的中断状态。如果它不会将 InterruptedException 传播给其调用者,那么它在捕获 InterruptedException 后应恢复中断状态:Thread.currentThread().interrupt()
所以,我尝试调整列表样例来理解这段话。但是,输出结果让我感到困惑。
PrimeProducer
public class CorrectPrimeProducer extends Thread {
private final BlockingQueue<BigInteger> queue;
public CorrectPrimeProducer(BlockingQueue<BigInteger> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+" interrupt status in producer:" + Thread.currentThread().isInterrupted());
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted()) {
queue.put(p = p.nextProbablePrime());
}
} catch (InterruptedException e) {
/* Allow thread to exit */
Thread.currentThread().interrupt();
System.out.println(Thread.currentThread().getName()+" interrupt status in producer catch:" + Thread.currentThread().isInterrupted());
}
}
}
主函数##
public static void main(String[] args) throws InterruptedException {
BlockingQueue<BigInteger> primes = new LinkedBlockingQueue<>();
CorrectPrimeProducer generator = new CorrectPrimeProducer(primes);
generator.start();
try {
while (needMorePrimes()) {
consume(primes.take());
}
} finally {
generator.interrupt();
}
TimeUnit.SECONDS.sleep(5);
System.out.println(generator.getName()+" interrupt status in main:"+generator.isInterrupted());
}
//do something
private static void consume(BigInteger take) {
System.out.println(take);
}
private static int counter = 1;
private static boolean needMorePrimes() {
counter++;
if(counter == 10){
// after counter reaches 10 return false
return false;
}
return true;
}
输出:
// when TimeUnit.SECONDS.sleep(5); in main class is not commented
Thread-0 interrupt status in producer:false
2
3
5
7
11
13
17
19
Thread-0 interrupt status in producer catch:true
Thread-0 interrupt status in main:false
//When TimeUnit.SECONDS.sleep(5); in main class is commented
Thread-0 interrupt status in producer:false
2
3
5
7
11
13
17
19
Thread-0 interrupt status in main:true
Thread-0 interrupt status in producer catch:true
问题
在主类的主线程中添加 TimeUnit.SECONDS.sleep(5) 就能重置执行线程(即生成器)的中断状态。如果我注释掉 TimeUnit.SECONDS.sleep(5) 方法,那么中断状态将保留。为什么会出现这种情况?如何解决?
书中提到一个线程应该只被它的拥有者中断。在上面的例子中,谁是拥有者?我认为是主方法线程。
return
或者throw
?除非他们明确记录下他们的库如何处理中断(这几乎从未发生),否则你是不知道的,或者,你可以直接和作者交流。我对使用中断来除了关闭进程之外的其他任何目的都感到非常不安。 - Solomon Slow