我在读Java并发在实践中的应用。章节中的中断策略
取消和关闭
它提到
除非任务显式地设计为在具有特定中断策略的服务中运行,否则任务不应假定其执行线程的中断策略。无论任务将中断解释为取消,还是对中断采取其他操作,都应注意保持执行线程的中断状态。如果它不打算将InterruptedException传播给它的调用者,它应该在捕获InterruptionException: 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问题
发布于 2020-08-25 21:25:04
通过添加TimeUnit.SECONDS.sleep(5),您将为线程的终止提供足够的时间。
当线程终止时,它的中断标志将被清除。
规范中没有记录这一点,但这是发生的事情。参见例如这个错误报告
这里没有违反规范,所以我已经将它作为一个增强请求而不是一个bug。可以说,缺乏规范是一个缺陷--我们确实故意指定“终止后的中断不需要影响”来处理中断状态存储在VM中,并且在线程结束后不再存在的事实。然而,我们忽略了在Thread.isInterrupted规范中反映这一点。
如果没有额外的sleep,我怀疑理论上您可以看到true和false中断状态,因为存在争用条件,但是由于线程调度,更有可能看到true。中断状态为false的时间窗口在抛出的异常与在catch块中恢复的中断状态之间的时间窗口非常小。
发布于 2020-08-25 20:49:59
只需在main类的主线程中添加TimeUnit.SECONDS.sleep(5)即可。正在重置执行线程(即生成器)中断状态。如果我注释TimeUnit.SECONDS.sleep(5)方法,那么在这种情况下,中断状态将被保留。为什么会发生这种情况,以及如何发生?
在主线程和CorrectPrimeProducer之间没有使用任何同步机制(除了阻塞队列),所以当主线程打印状态时-- CorrectPrimeProducer可能还没有保留中断状态(通过执行catch块指令),从而得到false。
当将sleep添加到主Thread时,只会增加CorrectPrimeProducer线程在主线程试图打印其状态之前通过调用catch块指令来保留中断状态的可能性。这就是它打印true的原因。
在书中提到,线程只应该被它的所有者打断。在上面的例子中,谁是所有者?我认为它的主要方法线。
在这种情况下,您是CorrectPrimeProducer线程的所有者(所有者是创建线程的代码),因此您可以决定中断对它意味着什么。例如,如果它被中断,您可以重新创建它(例如,对于来自java线程池的Thread,默认情况下会发生这种情况)。
https://stackoverflow.com/questions/63586688
复制相似问题