public class ThreadDemo {
private static boolean stopRequested;
public static void main(String args[]) throws InterruptedException {
Thread backageThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (!stopRequested)
i++;
}
});
backageThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
因为是while啊
你换成for试试
private static boolean stopRequested;
小布尔默认false,所以while处一直是true
一直在while,没有出来,执行不到stopRequested = true;这一句
boolean类型的初始值为false ,所以在while循环里面是出不来的,
无法执行到 TimeUnit.SECONDS.sleep(1); stopRequested = true;
你自己可以debugge 测一下
backageThread.start();执行到这一句的时候会启动线程调用线程中的run()方法;此时stopRequested = true;没有执行到,布尔的默认值是false;所以是死循环了;
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
说这两句没有执行的我也很费解,调用Thread 的start()方法后,循环是在另一个线程中执行的呀,为啥当前线程的后面两句会执行不到
你设置值布尔值在生命的时候直接设置就好了,反正都是private static
已经测试,不会死循环
public class Test1 {
private static boolean stopRequested;
public static void main(String args[]) throws InterruptedException {
Thread backageThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (!stopRequested){
i++;
System.out.println(i);
}
}
});
backageThread.start();
System.out.println("--backageThread-----");
TimeUnit.SECONDS.sleep(5);
stopRequested = true;
System.out.println("---stopRequested----");
// 输出:
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10
// 11
// 12
// 13
// 14
// 15
// 16
// 17
// 18
// 19
// 20
// 21
// --backageThread-----
// 22
// ---stopRequested----
}
}
测试了下,循环里只有i++这样就不会退出,像下面这样
while (!stopRequested){
i++;
}
但把i++替换为别的,或者加个语句就可以退出了
while (!stopRequested){
System.out.println("looper i:"+i+" stopRequested:"+stopRequested);
}
很怀疑是不是因为i是个无意义的变量,编译器在编译的时候把它优化了
stopRequested加上volatile,则该循环会马上终止,如果没有,则改循环还真不一定会终止
stopRequested = true;一定会运行到,但多线程下,另一个线程什么时候收到stopRequested被改变了,则是不定的
线程A修改stopRequested = true,线程B检测到数据有变动去内存中拷贝数据到本地
线程A有可能还没来得及将stopRequested = true的数据从高速缓存(work memory)写入主存,线程B就从主存中取了stopRequested的数据,所以还有可能是0,这样就发生了数据错误!
应该是指令从排问题
不可能死循环不出来,这个也跟指令重排没关系,父线sleep是静态方法,线程暂停不会释放锁,jvm不会进行句柄顺序调优,因此代码还是会按照逻辑顺序执行,你将时间设置短一点,或者最后输出任意字符到控制台就看出来了