返回信息流今天看effective java,230页,有这样一段代码:
```java
public class StopThread {
private static boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (!stopRequested) {
i++;
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
```
文中这样说:`你可能期待这个程序运行大约1秒`,然后主线程将stopRequested设置为true,致使循环终止。但实际上程序是不会终止的,虚拟机将这个代码
```java
while (!done)
i++;
```
优化为
```java
if(!done)
while(true)
i++;
```
这种优化称为 hoisting(提升)。 但当我把以上代码修改为这样之后,程序就停止了(其实就是我一开始给敲错了):
```java
public class StopThread {
private static boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (!stopRequested) {
i++;
System.out.println(""+i);
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
```
1秒后程序就停止了。 难道是因为这样 虚拟机就不会进行优化了嘛??求指教哇!!
这是一条镜像帖。来源:北邮人论坛 / java / #56070同步于 2017/4/28
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖
《effective java》为什么一个线程会停,一个不会呢?
lu1017222931
2017/4/28镜像同步6 回复
订阅后,新回复会通过你的通知中心匿名送达。
6 条回复
我的理解是,因为println里面有synchronized关键字,导致输出的时候变量i的值会立即回写主存。有了回写i的时间,线程在取i的值的时候,同时会把stopRequested的最新值取出来。所以导致线程可以停止。但是并不是说循环一次就能停止,这个与CPU的处理时间有很大关系,它会尽力有时间就去保证变量的可见性。如下面这个,在run方法中sleep3秒,CPU就有充足的空闲时间,来去保证变量的可见性。于是这样循环只输出一个0就结束了。
```Java
public class StopThread {
private static boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (!stopRequested) {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(i);
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
```
恩恩。。我知道这样可以,书里后面也说了,把stopRequested变量用volatile修饰可停止线程,但是我没想到拿System.out.println也可以停止[ema1][ema1][ema1]
【 在 nihaoa 的大作中提到: 】
: 把stopRequested用volatile修饰可停止线程。。。
意思就是 System.out.println会在输出i的同时,也让变量stopRequested被其他线程给看到。所有程序可以停止??
【 在 fengzhiya 的大作中提到: 】
: 我的理解是,因为println里面有synchronized关键字,导致输出的时候变量i的值会立即回写主存。有了回写i的时间,线程在取i的值的时候,同时会把stopRequested的最新值取出来。所以导致线程可以停止。但是并不是说循环一次就能停止,这个与CPU的处理时间有很大关系,它会尽力有时间就去保证变量的可见性。如下面这个,在run方法中sleep3秒,CPU就有充足的空闲时间,来去保证变量的可见性。于是这样循环只输出一个0就结束了。
: [md]
: ```Java
: ...................
是CPU有空闲或者有时间去执行的情况下。换句话说,不加volatile关键字,CPU按照JVM的要求还是会尽量将主存和工作内存的值就行同步,但不保证一定同步,因为CPU可能忙于别的事情,没有足够的时间。加了volatile相当于就是强制要求必须同步。