请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

在视屏中说使用Volatile不能停止线程,但是我加上一个休眠之后能够停止,请问为什么?

老师,请问为什么我再WrongWayVolatileCantStop.java里面的Producer的run方法里面加上一个休眠。好像是能够正常停止线程,请问为什么?

class Producer implements Runnable{

    public volatile boolean canceled = false;
    BlockingQueue storage;

    public Producer(BlockingQueue storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        int num = 0;
        try {
            while (num <= 100000 && !canceled) {
                if (num % 100 == 0) {
                    storage.put(num);//放到仓库中
                    System.out.println(num + "是100的倍数,被放到仓库中了。");
                }
                num++;
                //加上这句话,就能停止线程
                Thread.sleep(1);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            System.out.println("生产者结束运行");
        }
    }
}

正在回答 回答被采纳积分+3

3回答

慕婉清0327545 2020-04-25 23:31:04

我觉得是加上Thread.sleep(1)休眠之后,虽然看起来1millis时间很少,但是这个休眠是放在while循环里的,当生产者生产一个对象的时候,此时whil已经循环100次了,相当于每生产一个对象,就要休眠100millis。生产周期与消费周期巧好相等,所以仓库不会阻塞。也就是说每次循环都可以感知cancel的变化。

如果将消费者的消费周期设为300millis,即使Producer的run方法里面加上一个休眠,线程也不会正常停止。

Consumer consumer = new Consumer(storage);
while (consumer.needMoreNums()) {
    System.out.println(consumer.storage.take()+"被消费了");
    // 将休眠的时间从100改为300
    Thread.sleep(300);
}
System.out.println("消费者不需要更多数据了。");


0 回复 有任何疑惑可以回复我~
提问者 qq_慕数据1338854 2020-01-19 17:05:16

老师不好意思,我不是很懂老师的解答。我自己试了一下把消费时间调大,也把仓库容量调小。这时候就会出现停止不了线程的情况。我觉得是因为在Producer里的run方法加上一个一定时间的阻塞,导致仓库没有被塞满。所以生产者就不会进入休眠状态,这样volatile标记位还是有效的。请问这样理解对吗?

0 回复 有任何疑惑可以回复我~
  • 悟空 #1
    对的,加了sleep后,改变cancel的时候,生产者并不是停在put语句,所以就可以感知到cancel的变化
    回复 有任何疑惑可以回复我~ 2020-01-19 23:31:03
悟空 2020-01-19 10:40:15

在睡眠的时候,CPU会尽量利用这段时间来同步所有的变量,所以就可以看到属性的变化。

0 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信