Java ThreadLocal
2016-07-26 09:53
417 查看
参考 http://www.cnblogs.com/alphablox/archive/2013/01/20/2869061.html
参考 http://qifuguang.me/2015/09/02/[Java%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6%E4%B9%A0%E4%B8%83]%E8%A7%A3%E5%AF%86ThreadLocal/
一、定义
ThreadLocal就是对直接在thread中申明一个对象这种行为的封装,让调用者看起来就像静态变量一样。这样可以避免反复的申请和释放空间带来的性能损耗。
ThreadLocal在其内部定义了一个ThreadLocalMap,每当一个线程调用ThreadLocal的get方法时,它就会去map中寻找以该线程id为key的值,如果没找到,就会调用initialValue() 方法初始化该值并插入map,同时返回该值。
ThreadLocal在JDK中是这么定义的:
翻译过来大致是这样的:
ThreadLocal类用来提供线程内部的局部变量。这种变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量。ThreadLocal实例通常来说都是private static类型的,用于关联线程和线程的上下文。
可以总结为一句话:
ThreadLocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。
也就是说,ThreadLocal类允许我们创建只能被同一个线程读写的变量。因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的ThreadLocal变量。
二、代码实战
1、MyThreadLocal.java
2、执行方法
三、运行截图
参考 http://qifuguang.me/2015/09/02/[Java%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6%E4%B9%A0%E4%B8%83]%E8%A7%A3%E5%AF%86ThreadLocal/
一、定义
ThreadLocal就是对直接在thread中申明一个对象这种行为的封装,让调用者看起来就像静态变量一样。这样可以避免反复的申请和释放空间带来的性能损耗。
ThreadLocal在其内部定义了一个ThreadLocalMap,每当一个线程调用ThreadLocal的get方法时,它就会去map中寻找以该线程id为key的值,如果没找到,就会调用initialValue() 方法初始化该值并插入map,同时返回该值。
ThreadLocal在JDK中是这么定义的:
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its {@code get} or {@code set} method) has its own, independently initialized copy of the variable. {@code ThreadLocal} instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
翻译过来大致是这样的:
ThreadLocal类用来提供线程内部的局部变量。这种变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量。ThreadLocal实例通常来说都是private static类型的,用于关联线程和线程的上下文。
可以总结为一句话:
ThreadLocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。
也就是说,ThreadLocal类允许我们创建只能被同一个线程读写的变量。因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的ThreadLocal变量。
二、代码实战
1、MyThreadLocal.java
public class MyThreadLocal { public static final void log(String msg) { System.out.println(Thread.currentThread().getId() + ". " + msg); } public static final ThreadLocal<HashMap<Integer, Integer>> threadLocal = new ThreadLocal<HashMap<Integer, Integer>>() { //每一次在新的线程中调用threadLocal.get()时,都会调用到该方法,初始化threadLocalMap中key为当前线程id的值 protected HashMap<Integer, Integer> initialValue() { log("threadLocal_initialValue"); HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); map.put(-1, -1); return map; }; }; public class MyRunnable implements Runnable { int num; public MyRunnable(int num) { this.num = num; } @Override public void run() { HashMap<Integer, Integer> map = threadLocal.get(); log("before run " + map.toString()); int value; for (int i = 0; i < 5; i++) { value = num * 10 + i; map.put(i, value); log("map_put (" + i + "," + value + ")"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } log("after_put " + map.toString()); HashMap<Integer, Integer> map1 = new HashMap<Integer, Integer>(); map1.put(100, 100); //将新的map设置为threadLocalMap中key为当前线程id的值,下次通过get(),取的也是当前线程id的值 threadLocal.set(map1); log("threadLocal_set " + threadLocal.get().toString()); log("before threadLocal_remove "); //调用threadlocal.remove方法后,会执行initialValue方法,重新初始化map threadLocal.remove(); HashMap<Integer, Integer> map2 = threadLocal.get(); log("after threadLocal_remove " + (map2 == null ? "map = null" : map2.toString())); } } public MyThreadLocal() { log("MyThreadLocal init"); } class ClassA{ public String name; public ClassA() { log("ClassA init"); } } public static final ThreadLocal<MyThreadLocal> threadLocalTest1 = new ThreadLocal<MyThreadLocal>(); public static final ThreadLocal<ClassA> threadLocalTest2 = new ThreadLocal<ClassA>(); public void run() { log("run"); for (int i = 0; i < 3; i++) { // 注意:这里如果只是执行 new MyRunnable(i).run();方法,那么运行环境依然是主线程 new Thread(new MyRunnable(i)).start(); } } }
2、执行方法
public static void main(String[] args) { //threadlocat.get()获取的值也有可能为null MyThreadLocal mThreadLocal = MyThreadLocal.threadLocalTest1.get();//null ClassA mClassA = MyThreadLocal.threadLocalTest2.get();//null System.out.println("localThreadTest<MyThreadLocal>.get() " + (mThreadLocal == null?"is null":"not null")); System.out.println("localThreadTest<ClassA>.get() " + (mClassA == null?"is null":"not null")); mThreadLocal = new MyThreadLocal(); MyThreadLocal.log("main_thread"); mThreadLocal.run(); }
三、运行截图
相关文章推荐
- JAVA代码中加了Try...Catch的执行顺序
- spring的事务管理器有几种
- Java中的多态
- Java 浅析内部类
- OneExerciseOne创建一个类,它包含一个int域,一个char域,他们都没有初始化,验证Java执行了默认初始化
- File类常见方法
- Eclipse新建android工程就报错
- spring(2)装配Bean
- MyEclipse web项目重复打war包
- Java 素数
- java多态机制
- Java String中理解起来模糊的东西,我来给我扫扫盲。(String类的intern() 、equal()、 == )
- spring配置文件读取${username}问题
- myeclipse10 svn: E175002 svn:unable to connect to a repository at URL
- Java设计模式—门面模式(带案例分析)
- Java设计模式—门面模式(带案例分析)
- SpringMVC
- Spring MVC 实现文件上传及批量上传
- Spring 匹配注入规则
- Java去除字符串中的空格、回车、换行符、制表符 及 常用正则表达式