System.out.println当输出一个属性的时候是会读相关属性的真实内存地址上的数据同时做一次同步
2017-12-01 11:32
375 查看
package com.yikuyi.volatileTest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RunThread extends Thread{
private static final Logger logger = LoggerFactory.getLogger(RunThread.class);
private boolean running = true;
private int a = 0;
private void setRunning(boolean running){
System.out.println("&&&&&&&&&&&&&&&&----setRunning-----"+Thread.currentThread().getName());
this.running = running;
}
@Override
public void run(){
System.out.println("进入run方法......");
System.out.println("----run-------"+Thread.currentThread().getName()+"--------running:"+running);
while(running){
// System.out.println("--------while--------"+Thread.currentThread().getName()+"----------"+running);
a++;
}
System.out.println("线程停止"+"--------------------"+Thread.currentThread().getName());
}
public static void main(String[] args) throws InterruptedException {
RunThread runThread = new RunThread();
runThread.start();
Thread.sleep(3000);
runThread.setRunning(false);
System.out.println("--------running-----set-----false-----");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"************"+runThread.running+"**********");
}
}
楼主,你这个问题其实很常见,这个是由java虚拟机的机制导致的,虚拟机为了效率,在处理线程类的属性时会创建一个临时属性,比如你一个线程类有一个子属性int a,在线程高速运行的时候,线程外部对这个a的修改并不能及时传达至内部,因为是非原子操作,同样线程内部对这个a 的修改也不能及时传达至外部,因为在线程外部调用这个属性a和线程内部调用这个属性a其实不是一个内存地址,只是看起来是同一个变量罢了,这个类似一种线程内部的缓存机制,可以确定的是当这个线程运行结束时,这个属性的值才会统一,至于在线程运行期间这个属性的值是不是能同步是不确定的,解决的办法可以采用sleep,你那个System.out.println也算是一种解决办法,我理解的当输出一个属性的时候是会读相关属性的真实内存地址上的数据同时做一次同步,除了这两个看起来不雅的办法,还可以用原子操作来解决可以参考下 AtomicInteger 这个类的api,这个类是一个原子操作的类,可以确保你多线程运行过程中内部和外部数据的统一,但是也略微降低了程序效率
查看地址:http://bbs.csdn.net/topics/391077210?page=1
package com.yikuyi.volatileTest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RunThread extends Thread{
private static final Logger logger = LoggerFactory.getLogger(RunThread.class);
private boolean running = true;
private int a = 0;
private void setRunning(boolean running){
System.out.println("&&&&&&&&&&&&&&&&----setRunning-----"+Thread.currentThread().getName());
this.running = running;
}
@Override
public void run(){
System.out.println("进入run方法......");
System.out.println("----run-------"+Thread.currentThread().getName()+"--------running:"+running);
while(running){
// System.out.println("--------while--------"+Thread.currentThread().getName()+"----------"+running);
a++;
}
System.out.println("线程停止"+"--------------------"+Thread.currentThread().getName());
}
public static void main(String[] args) throws InterruptedException {
RunThread runThread = new RunThread();
runThread.start();
Thread.sleep(3000);
runThread.setRunning(false);
System.out.println("--------running-----set-----false-----");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"************"+runThread.running+"**********");
}
}
楼主,你这个问题其实很常见,这个是由java虚拟机的机制导致的,虚拟机为了效率,在处理线程类的属性时会创建一个临时属性,比如你一个线程类有一个子属性int a,在线程高速运行的时候,线程外部对这个a的修改并不能及时传达至内部,因为是非原子操作,同样线程内部对这个a 的修改也不能及时传达至外部,因为在线程外部调用这个属性a和线程内部调用这个属性a其实不是一个内存地址,只是看起来是同一个变量罢了,这个类似一种线程内部的缓存机制,可以确定的是当这个线程运行结束时,这个属性的值才会统一,至于在线程运行期间这个属性的值是不是能同步是不确定的,解决的办法可以采用sleep,你那个System.out.println也算是一种解决办法,我理解的当输出一个属性的时候是会读相关属性的真实内存地址上的数据同时做一次同步,除了这两个看起来不雅的办法,还可以用原子操作来解决可以参考下 AtomicInteger 这个类的api,这个类是一个原子操作的类,可以确保你多线程运行过程中内部和外部数据的统一,但是也略微降低了程序效率
查看地址:http://bbs.csdn.net/topics/391077210?page=1
相关文章推荐
- 关于使用System.out.println()向控制台输出数据和使用out.println()向页面输出数据效率的问题
- Eclipse:Android开发中如何查看System.out.println的输出内容
- System.out.println()不在控制台中显示输出
- 更改System.out.println()的输出路径
- System.out.println()输出到指定文件里
- 当使用System,out.println()打印一个对象是自动调用toString方法
- 当一个控件属性不存在的时候,IDE会出错在这里(说明是TWinControl.ReadState在读属性,并执行相关动作)
- 如何将System.out的内容重定向输出到一个界面上的文本框中?
- byte a =(byte)129; System.out.println(a);//会输出什么呢?
- hadoop中查看System.out.println输出
- 重定向控制台System.out.println输出到文件,再重定向回控制台
- 在使用Linq to SQL并序列化一个数据对象的时候报System.InvalidOperationException异常,序列化类型XXX的对象时检测到循环引用。
- Java应用程序中System.out.println输出中文乱码
- Eclipse:Android开发中如何查看System.out.println的输出内容
- 打印输出语句:System.out.println("内容"+i+1+"内容");与System.out.println("内容"+(i+1)+"内容");的区别
- System.out.println将内容输出到文件保存
- System.out.println() 和 log4j 的 Logger 循环输出100万次。
- 一个最简单的java程序,没有任何import 为什么还能System.out.println
- Logcat中查看System.out.println()输出的内容(转)
- 恒大的一个题,关于System.out.print和System.err.println以及静态和构造函数的