package com.guowei;
class ThreadVolatileDemo extends Thread {
public volatile boolean flag = true;
@Override
public void run() {
System.out.println("子线程开始执行...");
while (flag) {
}
System.out.println("子线程执行结束...");
}
public void setFlag(boolean flag){
this.flag=flag;
}
}
public class ThreadVolatile {
public static void main(String[] args) throws InterruptedException {
ThreadVolatileDemo threadVolatileDemo = new ThreadVolatileDemo();
threadVolatileDemo.start();
// threadVolatileDemo.setFlag(false);
Thread.sleep(3000);
//主线程修改共享全局变量为false
threadVolatileDemo.setFlag(false);
System.out.println("flag已结修改false!");
Thread.sleep(1000);
System.out.println(threadVolatileDemo.flag);
}
}
上例中,必须使用volatile关键字才可以使main线程和threadVolatileDemo线程发生交互。
而在下例中,不使用volatile关键字也可以起到相同的作用。
为什么?
package com.guowei;
class ThreadTrain2 implements Runnable {
private int train1Count = 100;
public boolean flag = true;
@Override
public void run() {
while (train1Count > 0) {
if (flag) {
try {
Thread.sleep(50);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName()+ ",出售第" + (100 - train1Count + 1) + "票");
train1Count--;
}else{
try {
Thread.sleep(50);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName()+ ",flag为-------->false");
}
}
}
}
public class ThreadDemo2 {
public static void main(String[] args) throws InterruptedException {
ThreadTrain2 threadTrain2 = new ThreadTrain2();
Thread t1 = new Thread(threadTrain2, "t1");
t1.start();
Thread t2 = new Thread(threadTrain2, "t2");
t2.start();
Thread.sleep(400);
threadTrain2.flag = false;
}
}
我自己的理解:创建线程t1与t2时,引用了threadTrain2对象,直接使用threadTrain2作为自己的本地内存,并没有拷贝副本,也就是说,这几个线程均拥有threadTrain2的资源,当threadTrain2内容发生变化时,引用地址并没有发生变化,所以就能读取到原来地址中已经变化后的新值。