java基础-ThreadLocal变量和普通变量的区别

java提供了ThreadLocal这个类型,具有该类型的成员变量,每个使用到该变量的线程都保留一份该属性的备份数据,在线程内部对该属性的操作都是自己备份的数据,所以声明为ThreadLocal类型的成员变量都是线程安全的。

简单测试了一下ThreadLocal类型的成员和普通成员的区别,在多线程环境,每个线程都会存有一个ThreadLocal的值,而普通成员则是线程共享的。

import java.util.Date;

public class MyThreadLocal {
	private ThreadLocal date = new ThreadLocal();
	private Date d = null;

	public void process(){
		if(date.get()==null){
			date.set(new Date());
			System.out.println("<span style="font-family: Arial, Helvetica, sans-serif;">thread local fileld</span>:"+date.get());
		}
	}
	//操作普通成员,需要同步处理
	public void p(){
		synchronized(MyThreadLocal.class){
			if(d==null){
				d = new Date();
				System.out.println("ordinary field:"+d);
			}
		}
	}
}

测试类:定义一个MyThreadLocal对象实例,由5个线程同时访问它的方法。

import java.util.Date;

public class Test {
	public static void main(String[] args) {
		final MyThreadLocal t = new MyThreadLocal();
		for(int i = 0;i<5;i++){
			Thread thread = new Thread(){
				public void run(){
					t.process();
					t.p();
				}
			};
			thread.start();
		}
		Date d1 = new Date();
		Date d2 = new Date();
		System.out.println(d1==d2);
		System.out.println(d1.hashCode()==d2.hashCode());
	}
}

测试结果:

false
true
thread local fileld:Fri Apr 10 14:47:30 CST 2015
ordinary field:Fri Apr 10 14:47:31 CST 2015
thread local fileld:Fri Apr 10 14:47:30 CST 2015
thread local fileld:Fri Apr 10 14:47:30 CST 2015
thread local fileld:Fri Apr 10 14:47:30 CST 2015
thread local fileld:Fri Apr 10 14:47:30 CST 2015

测试结果分析:很显然共享的成员变量d只被一个线程初始化了一次,所以p方法的代码只执行了一次;而ThreadLocal成员变量,每个访问该变量的线程都会自己创建一个备份数据,process方法被执行了五次。此外,还发现两次new Date()得到的对象的hashCode很容易相等,但的确是两个不同对象。

时间: 2024-12-19 07:23:04

java基础-ThreadLocal变量和普通变量的区别的相关文章

java基础--JDK安装、环境变量配置、工具开发第一个程序、数据类型、运算符

**-----Java基础大纲-----**   **-----本章节-----** 1.Java语言的历史.特点及工作原理 2.JRE和JDK的介绍 3.Java运行环境和开发工具 4.Java基础语法 **-----下一章节-----** 5.条件语句 6.循环 7.数组 ============================================== 一:历史及开发准备 1.Java发展历程及来源 (1)发展历程 1996年1月,Sun公司发布了Java的第一个开发工具包(JD

不惑JAVA之JAVA基础 - ThreadLocal

ThreadLocal在数据库连接和session管理下有广泛的应用,了解ThreadLocal对struts.spring等开源代码的理解有很大的帮助. ThreadLocal如果单纯从名字上来看像是"本地线程"这么个意思,只能说这个名字起的确实不太好,很容易让人产生误解,ThreadLocalVariable(线程本地变量)应该是个更好的名字.我们先看一下官方对ThreadLocal的描述: 该类提供了线程局部 (thread-local) 变量.这些变量不同于它们的普通对应物,因

关于Java基础知识 String StringBuffer StringBuilder三者的区别

Java基础中String StringBuffer StringBuilder 以下介绍 相同点:String,StringBuffer,StringBuilder最终底层存储与操作的都是char数组,StringBuffer和StringBuilder都继承了AbstractStringBuilder 不同点:String:char数组是final的,不可变,修改String时实际上是new一个新String对象返回,线程安全,频繁的增删操作时不建议使用 StringBuffer:线程安全(

黑马程序员-java基础知识+环境搭建和变量配置

一.dos命令 软件:是一系列按照特定顺序组织的计算机数据和指令的集合. 交互方式:图形化界面.命令行方式 dir  directory 显示文件和子目录 cd   change directory 改变当前的路径(进入指定目录) md   make directory 新建一个子目录(文件夹) rd   remove directory 删除一个子目录(文件夹) cd.. 返回上一文件夹 cd/  返回根目录(磁盘) del  delete 删除文件 (不走回收站)   del *.txt(删

Java基础2(2015-8-3)变量与数据类型

1.写程序就是重复在做内存存取操作,把数据存入内存,需要时根据地址取出来做处理. 2.变量是程序当中最基本的存储单元,就是内存中分配的一块内存区间,用于存放相应的数据,通过变量名可访问里面的相关数据. 3.根据数据类型分配内存空间. 4.变量必须初始化之后才能使用: 5.int a=b=c=5;该连等的写法是错的:int a=3,b=6,c=9;对的: 6.不能申明同名变量,地址是唯一标识: 7.关键字不能作为变量名: 8.变量名区分大小写. 9.Java强类型语言,对于每一种数据都定义了明确的

java基础JDK jvm path环境变量

JDk=JRE +java的开发工具(javac.exe java.exe javadoc.exe)JRE =JVM +Java核心类库 2.为什么 要配置 path环境变量 ?如何配置?JAVA_HOME =bin的上一层目录path =%JAVA_HOME%\bin 3.常用的命令行操作都有哪些(至少四个)cd mdrddelcd ..cd/ 4.创建如下类 使得运行的话可以输出创建一个java 文件: ChairMan.javapublic  class   ChairMan{ publi

Java基础(二)【变量_数据类型】

1.变量 三要素: 数据类型 变量名 变量值 首先,让我们来看看变量命名的规则 开头              字母.下划线.美元符号.人民币符号: 后续              字母.下划线.美元符号.人民币符号.数字: 命名法:a. 驼峰命名法      变量名首字母要小写,其余后续有含义的单词首字母大写 Eg:stuName,stuAge,orderDetails b. 帕斯卡命名法: 在命名的时候将首字母大写,如: 程序代码public void DisplayInfo(); stri

java基础-ThreadLocal

来聊一下ThreadLocal的实现原理和它的内存泄漏问题 首先来看一个官方示例,这里构造了一个ThreadId类,其作用是在每个线程中保存各自的id,此id全局唯一,通过get可以获取id. 1 private static class ThreadId { 2 // Atomic integer containing the next thread ID to be assigned 3 private static final AtomicInteger nextId = new Atom

Java基础之&quot;==&quot;和 和 equals 方法的区别

一."=="操作符 ==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符. 如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存) ,变量也占用一块内存,例如 Objet obj = new Object();变量 obj 是一个内存,new Object()是另一个内存,此时,变量 obj 所对应的内存中存储的数值就是对象占用的那块内存