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