Java 并发 - 中断策略
Java Concurrency - Interruption Policies
我正在阅读 Java 并发实践
。在
章的中断政策部分
取消和关闭
它被提及
A task should not assume anything about the interruption policy of its executing thread unless it is explicitly designed to run within a service that has a specific interruption policy. Whether a task interprets interruption as cancellation or takes some other action on interruption, it should take care to preserve the executing thread's interruption status. If its not going to propagate InterruptedException to its caller, it should restore the interruption status after catching InterruptionException:
Thread.currentThread().interrupt()
所以我尝试尝试使用列表示例来理解。但我对输出感到困惑。
主要生产者
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
问题
只需在主class的主线程中添加TimeUnit.SECONDS.sleep(5)即可。正在执行的线程(即生成器)中断状态正在重置。如果我评论 TimeUnit.SECONDS.sleep(5) 方法,那么在这种情况下会保留中断状态。为什么会发生这种情况以及如何发生?
书中提到线程只能由其所有者中断。在上面的例子中,所有者是谁?我认为它的主要方法线程。
Just by adding TimeUnit.SECONDS.sleep(5) in main thread in main class. The executing thread (ie, generator) interrupt status is getting reset. If I comment the TimeUnit.SECONDS.sleep(5) method then in that case interrupt status is retained. Why is this happening and how ?
你没有在主线程和 CorrectPrimeProducer
之间使用任何同步机制(除了阻塞队列)所以当主线程打印状态时 - CorrectPrimeProducer
可能没有保留被中断的状态(通过执行 catch
块指令)因此你得到 false
作为结果。
当您将 sleep
添加到主线程 Thread
时,您只是增加了 CorrectPrimeProducer
线程通过在主线程之前调用 catch
块指令来保留中断状态的可能性线程尝试打印它的状态。这就是它打印 true
.
的原因
In book it's mentioned A thread should be interrupted only by its owner . Here in the above example who is the owner ? I think its main method thread.
在这种情况下,您是 CorrectPrimeProducer
线程的所有者(所有者是创建线程的代码),因此您可以决定中断对它意味着什么。例如,如果它被中断,您可以重新创建它(例如,默认情况下,java 线程池中的 Thread
s 会发生这种情况)。
通过添加 TimeUnit.SECONDS.sleep(5)
,您为线程终止提供了足够的时间。
当一个线程终止时,它的中断标志被清除。
规范中没有记录,但确实如此。参见示例 this bug report:
There is no specification being violated here so I've made this an enhancement request rather than a bug. Arguably the lack of specification is a bug - we did intentionally specify that "interrupt after termination need have no affect" to deal with the fact that the interrupt state is stored in the VM and no longer exists once a thread has terminated. However we neglected to reflect that in the Thread.isInterrupted spec.
如果没有额外的 sleep
,我怀疑理论上您可以同时看到 true
和 false
中断状态,因为存在竞争条件,但您更有可能看到true
感谢线程调度。 window 中断状态为假的时间,从抛出异常到在 catch 块中恢复中断状态,非常小。
我正在阅读 Java 并发实践 。在
章的中断政策部分取消和关闭
它被提及
A task should not assume anything about the interruption policy of its executing thread unless it is explicitly designed to run within a service that has a specific interruption policy. Whether a task interprets interruption as cancellation or takes some other action on interruption, it should take care to preserve the executing thread's interruption status. If its not going to propagate InterruptedException to its caller, it should restore the interruption status after catching InterruptionException: Thread.currentThread().interrupt()
所以我尝试尝试使用列表示例来理解。但我对输出感到困惑。
主要生产者
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
问题
只需在主class的主线程中添加TimeUnit.SECONDS.sleep(5)即可。正在执行的线程(即生成器)中断状态正在重置。如果我评论 TimeUnit.SECONDS.sleep(5) 方法,那么在这种情况下会保留中断状态。为什么会发生这种情况以及如何发生?
书中提到线程只能由其所有者中断。在上面的例子中,所有者是谁?我认为它的主要方法线程。
Just by adding TimeUnit.SECONDS.sleep(5) in main thread in main class. The executing thread (ie, generator) interrupt status is getting reset. If I comment the TimeUnit.SECONDS.sleep(5) method then in that case interrupt status is retained. Why is this happening and how ?
你没有在主线程和 CorrectPrimeProducer
之间使用任何同步机制(除了阻塞队列)所以当主线程打印状态时 - CorrectPrimeProducer
可能没有保留被中断的状态(通过执行 catch
块指令)因此你得到 false
作为结果。
当您将 sleep
添加到主线程 Thread
时,您只是增加了 CorrectPrimeProducer
线程通过在主线程之前调用 catch
块指令来保留中断状态的可能性线程尝试打印它的状态。这就是它打印 true
.
In book it's mentioned A thread should be interrupted only by its owner . Here in the above example who is the owner ? I think its main method thread.
在这种情况下,您是 CorrectPrimeProducer
线程的所有者(所有者是创建线程的代码),因此您可以决定中断对它意味着什么。例如,如果它被中断,您可以重新创建它(例如,默认情况下,java 线程池中的 Thread
s 会发生这种情况)。
通过添加 TimeUnit.SECONDS.sleep(5)
,您为线程终止提供了足够的时间。
当一个线程终止时,它的中断标志被清除。
规范中没有记录,但确实如此。参见示例 this bug report:
There is no specification being violated here so I've made this an enhancement request rather than a bug. Arguably the lack of specification is a bug - we did intentionally specify that "interrupt after termination need have no affect" to deal with the fact that the interrupt state is stored in the VM and no longer exists once a thread has terminated. However we neglected to reflect that in the Thread.isInterrupted spec.
如果没有额外的 sleep
,我怀疑理论上您可以同时看到 true
和 false
中断状态,因为存在竞争条件,但您更有可能看到true
感谢线程调度。 window 中断状态为假的时间,从抛出异常到在 catch 块中恢复中断状态,非常小。