Java并发中断策略

Java并发中断策略,java,multithreading,concurrency,java.util.concurrent,Java,Multithreading,Concurrency,Java.util.concurrent,我正在读书。在第章的“中断策略”一节中 取消和关闭 它提到 任务不应该假设其执行线程的中断策略,除非它被明确设计为在具有特定中断策略的服务中运行。无论任务是将中断解释为取消还是对中断执行其他操作,它都应该注意保持执行线程的中断状态。如果它不打算将InterruptedException传播到其调用者,它应该在捕获InterruptedException后恢复中断状态: Thread.currentThread().interrupt() 所以我试着用清单示例来理解。但我对输出感到困惑 主要生产者

我正在读书。在第章的“中断策略”一节中

取消和关闭 它提到

任务不应该假设其执行线程的中断策略,除非它被明确设计为在具有特定中断策略的服务中运行。无论任务是将中断解释为取消还是对中断执行其他操作,它都应该注意保持执行线程的中断状态。如果它不打算将InterruptedException传播到其调用者,它应该在捕获InterruptedException后恢复中断状态: Thread.currentThread().interrupt()

所以我试着用清单示例来理解。但我对输出感到困惑

主要生产者 问题:

  • 只需在主类的主线程中添加TimeUnit.SECONDS.sleep(5)。正在执行的线程(即生成器)中断状态正在重置。如果我对TimeUnit.SECONDS.sleep(5)方法进行注释,那么在这种情况下,将保留中断状态。为什么会发生这种情况,如何发生

  • 在书中提到一个线程只能被它的所有者打断。在上面的例子中,谁是所有者?我认为它的主要方法是线程

  • 只需在主类的主线程中添加TimeUnit.SECONDS.sleep(5)。正在执行的线程(即生成器)中断状态正在重置。如果我对TimeUnit.SECONDS.sleep(5)方法进行注释,那么在这种情况下,将保留中断状态。为什么会发生这种情况,如何发生

    您没有在主线程和
    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