Java并发中断策略
我正在读书。在第章的“中断策略”一节中 取消和关闭 它提到 任务不应该假设其执行线程的中断策略,除非它被明确设计为在具有特定中断策略的服务中运行。无论任务是将中断解释为取消还是对中断执行其他操作,它都应该注意保持执行线程的中断状态。如果它不打算将InterruptedException传播到其调用者,它应该在捕获InterruptedException后恢复中断状态: Thread.currentThread().interrupt() 所以我试着用清单示例来理解。但我对输出感到困惑 主要生产者 问题:Java并发中断策略,java,multithreading,concurrency,java.util.concurrent,Java,Multithreading,Concurrency,Java.util.concurrent,我正在读书。在第章的“中断策略”一节中 取消和关闭 它提到 任务不应该假设其执行线程的中断策略,除非它被明确设计为在具有特定中断策略的服务中运行。无论任务是将中断解释为取消还是对中断执行其他操作,它都应该注意保持执行线程的中断状态。如果它不打算将InterruptedException传播到其调用者,它应该在捕获InterruptedException后恢复中断状态: Thread.currentThread().interrupt() 所以我试着用清单示例来理解。但我对输出感到困惑 主要生产者
CorrectPrimeProducer
之间使用任何同步机制(除了阻塞队列),因此当主线程打印状态时,CorrectPrimeProducer
可能尚未保留中断状态(通过执行catch
阻塞指令)因此,结果是false
当您将睡眠
添加到主线程
时,您只需在主线程尝试打印其状态之前调用捕获
块指令,从而增加线程保持中断状态的可能性。这就是它打印true
的原因
在书中提到一个线程只能被它的所有者打断。在上面的例子中,谁是所有者?我认为它的主要方法是线程
在这种情况下,您是CorrectPrimeProducer
线程的所有者(所有者是创建线程的代码),因此您可以决定中断对它意味着什么。例如,如果它被中断,您可以重新创建它(例如,java线程池中的线程默认情况下会发生这种情况)。通过添加TimeUnit.SECONDS.sleep(5)
您为线程提供了足够的终止时间
当线程终止时,其中断标志被清除
规范中没有记录这一点,但实际情况就是如此。例如,见:
这里没有违反任何规范,所以我提出了一个增强请求,而不是一个bug。可以说,缺少规范是一个缺陷——我们确实有意指定“终止后中断不需要影响”,以处理中断状态存储在VM中,并且一旦线程终止就不再存在的事实。然而,我们忽略了在Thread.isInterrupted规范中反映这一点
如果没有额外的睡眠
,我怀疑在理论上你可以看到真
和假
中断状态,因为存在竞争条件,但由于线程调度,你更可能看到真
。在抛出异常和在catch块中恢复中断状态之间,中断状态为false的时间窗口非常小。谢谢。但是如果使用了sleep,则主线程会将CorrectPrimeProducer线程的中断状态打印为false。Re,“任务不应假设任何有关中断策略的内容。。。“是的,不应该。但是,如果您的代码调用了任何库代码,那么您怎么知道库作者没有假定中断意味着整个过程正在关闭,他们可以放弃正在进行的工作,而返回或抛出,而不进行清理?除非他们明确地记录了他们的库如何处理中断(这几乎是不可能的),或者,你自己与作者交谈,否则你不知道。我对将中断用于除关闭进程之外的任何其他目的感到非常不安。
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