首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java并发-中断策略

Java并发-中断策略
EN

Stack Overflow用户
提问于 2020-08-25 20:34:32
回答 2查看 157关注 0票数 4

我在读Java并发在实践中的应用。章节中的中断策略

取消和关闭

它提到

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

所以我试着用列表样本来理解。但我对产出感到困惑。

PrimeProducer

代码语言:javascript
复制
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());
        }
    }
}

主要方法

代码语言:javascript
复制
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; 
    }

输出:

代码语言:javascript
复制
// 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
代码语言:javascript
复制
//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

问题

  1. 只需在main类的主线程中添加TimeUnit.SECONDS.sleep(5)即可。正在重置执行线程(即生成器)中断状态。如果我注释TimeUnit.SECONDS.sleep(5)方法,那么在这种情况下,中断状态将被保留。为什么会发生这种情况,以及如何发生?
  2. 在书中提到,线程只应该被它的所有者打断。在上面的例子中,谁是所有者?我认为它的主要方法线。
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-08-25 21:25:04

通过添加TimeUnit.SECONDS.sleep(5),您将为线程的终止提供足够的时间。

当线程终止时,它的中断标志将被清除。

规范中没有记录这一点,但这是发生的事情。参见例如这个错误报告

这里没有违反规范,所以我已经将它作为一个增强请求而不是一个bug。可以说,缺乏规范是一个缺陷--我们确实故意指定“终止后的中断不需要影响”来处理中断状态存储在VM中,并且在线程结束后不再存在的事实。然而,我们忽略了在Thread.isInterrupted规范中反映这一点。

如果没有额外的sleep,我怀疑理论上您可以看到truefalse中断状态,因为存在争用条件,但是由于线程调度,更有可能看到true。中断状态为false的时间窗口在抛出的异常与在catch块中恢复的中断状态之间的时间窗口非常小。

票数 1
EN

Stack Overflow用户

发布于 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,默认情况下会发生这种情况)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63586688

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档