在视屏中说使用Volatile不能停止线程,但是我加上一个休眠之后能够停止,请问为什么?
来源:5-11 错误停止2

qq_慕数据1338854
2020-01-19
老师,请问为什么我再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回答
-
慕婉清0327545
2020-04-25
我觉得是加上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("消费者不需要更多数据了。");
00 -
qq_慕数据1338854
提问者
2020-01-19
老师不好意思,我不是很懂老师的解答。我自己试了一下把消费时间调大,也把仓库容量调小。这时候就会出现停止不了线程的情况。我觉得是因为在Producer里的run方法加上一个一定时间的阻塞,导致仓库没有被塞满。所以生产者就不会进入休眠状态,这样volatile标记位还是有效的。请问这样理解对吗?
012020-01-19 -
悟空
2020-01-19
在睡眠的时候,CPU会尽量利用这段时间来同步所有的变量,所以就可以看到属性的变化。
00
相似问题
为什么休眠了程序就一定运行完成
回答 2
关于volatile禁止指令重排
回答 1