简体   繁体   English

Java 并发 - 中断策略

[英]Java Concurrency - Interruption Policies

I am reading Java Concurrency in Practice .我正在阅读Java 并发实践 In section Interruption Policies in chapter在章节中断政策部分

Cancellation and Shutdown取消和关闭

Its mentioned它提到

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()如果它不打算将 InterruptedException 传播给它的调用者,它应该在捕获 InterruptionException 后恢复中断状态: Thread.currentThread().interrupt()

So I tried to play around with listing sample to understand.所以我试着玩弄清单样本来理解。 But I am confused with the output.但我对输出感到困惑。

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());
        }
    }
}

main method##主要方法##

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; 
    }

Output:输出:

// 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

Question

  1. Just by adding TimeUnit.SECONDS.sleep(5) in main thread in main class.只需在主类的主线程中添加 TimeUnit.SECONDS.sleep(5) 即可。 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.如果我评论 TimeUnit.SECONDS.sleep(5) 方法,那么在这种情况下会保留中断状态。 Why is this happening and how ?为什么会发生这种情况以及如何发生?

  2. 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.我认为它的主要方法线程。

Just by adding TimeUnit.SECONDS.sleep(5) in main thread in main class.只需在主类的主线程中添加 TimeUnit.SECONDS.sleep(5) 即可。 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.如果我评论 TimeUnit.SECONDS.sleep(5) 方法,那么在这种情况下会保留中断状态。 Why is this happening and how ?为什么会发生这种情况以及如何发生?

You are not using any synchronization mechanism (apart from blocking queue) between the main thread and the CorrectPrimeProducer so when the main thread prints the status - the CorrectPrimeProducer may not have preserved the interrupted status yet (by performing catch block instructions) thus you get false as the result.您没有在主线程和CorrectPrimeProducer之间使用任何同步机制(除了阻塞队列),因此当主线程打印状态时 - CorrectPrimeProducer可能尚未保留中断状态(通过执行catch块指令)因此您得到false作为结果。

When you add sleep to the main Thread you just increase the possibility that the CorrectPrimeProducer thread preserves the interruption status by invoking catch block instructions before the main thread tries to print it's status.当您将sleep添加到主Thread您只会增加CorrectPrimeProducer线程通过在主线程尝试打印其状态之前调用catch块指令来保留中断状态的可能性。 That is why it prints true .这就是它打印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.我认为它的主要方法线程。

In this case you are the owner (the owner is the code that creates the thread) of the CorrectPrimeProducer thread so you decide what interruption means to it.在这种情况下,您是CorrectPrimeProducer线程的所有者(所有者是创建线程的代码),因此您可以决定中断对它意味着什么。 For example you could recreate it if it was interrupted (this happens for example for Thread s from java thread pools by default).例如,如果它被中断,您可以重新创建它(例如,默认情况下,Java 线程池中的Thread会发生这种情况)。

By adding TimeUnit.SECONDS.sleep(5) you are giving enough time for the thread to terminate.通过添加TimeUnit.SECONDS.sleep(5)您为线程终止提供了足够的时间。

When a thread terminates, its interrupt flag is cleared.当一个线程终止时,它的中断标志被清除。

This is not documented in the specification, but it's what happens.这在规范中没有记录,但这就是发生的事情。 See for example 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.可以说缺乏规范是一个错误——我们确实特意指定了“终止后的中断不需要有影响”来处理这样一个事实,即中断状态存储在 VM 中,一旦线程终止就不再存在。 However we neglected to reflect that in the Thread.isInterrupted spec.然而,我们忽略了在 Thread.isInterrupted 规范中反映这一点。

Without the extra sleep , I suspect that in theory you could see both true and false interrupt status because there's a race condition, but it's far more likely you will see true thanks to thread scheduling.如果没有额外的sleep ,我怀疑理论上您可以看到truefalse中断状态,因为存在竞争条件,但由于线程调度,您更有可能看到true The time window where the interrupt status is false, between the exception being thrown and it the interrupt status being restored in the catch block, is incredibly small.在抛出异常和在 catch 块中恢复中断状态之间,中断状态为假的时间窗口非常小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM