ThreadLocal线程变量
(已迁移)
-- Thread类里面有一个threadLocals成员变量

-- ThreadLocal类下面有一个静态内部类ThreadLocalMap

-- ThreadLocal类下有get,set,remove方法





-- ThreadLocal使用:
1 public class Solution { 2 3 private static ThreadLocal<String> threadLocal1 = new ThreadLocal<>() { //初始化方式1,重写 4 @Override 5 public String initialValue() { 6 return "initialVal1"; 7 } 8 }; 9 private static ThreadLocal<String> threadLocal2 = ThreadLocal.withInitial(() -> "initialVal2"); //初始化方式2 10 11 public static void method() { 12 Thread td1 = new Thread(() -> { 13 threadLocal1.set("thread1_threadLocal1"); 14 threadLocal2.set("thread1_threadLocal2"); 15 16 System.out.println("thread1_threadLocal1 : " + threadLocal1.get()); //get返回线程局部变量的副本值 17 System.out.println("thread1_threadLocal2 : " + threadLocal2.get()); 18 19 threadLocal1.remove(); 20 threadLocal2.remove(); 21 22 System.out.println("after remove : " + " threadLocal1 : " + threadLocal1.get()); 23 System.out.println("after remove : " + " threadLocal2 : " + threadLocal2.get()); 24 }); 25 26 Thread td2 = new Thread(() -> { 27 threadLocal1.set("thread2_threadLocal1"); 28 threadLocal2.set("thread2_threadLocal2"); 29 30 try { 31 Thread.sleep(2000); 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 36 System.out.println("after sleep 2000ms, thread2_threadLocal1 : " + threadLocal1.get()); 37 System.out.println("after sleep 2000ms, thread2_threadLocal2 : " + threadLocal2.get()); 38 39 threadLocal1.remove(); 40 threadLocal2.remove(); 41 System.out.println("after remove : " + " threadLocal1 : " + threadLocal1.get()); 42 System.out.println("after remove : " + " threadLocal2 : " + threadLocal2.get()); 43 }); 44 45 td1.start(); 46 td2.start(); 47 } 48 } 49 50 /* 51 * thread1_threadLocal1 : thread1_threadLocal1 52 * thread1_threadLocal2 : thread1_threadLocal2 53 * after remove : threadLocal1 : null 54 * after remove : threadLocal2 : null 55 * after sleep 2000ms, thread2_threadLocal1 : thread2_threadLocal1 56 * after sleep 2000ms, thread2_threadLocal2 : thread2_threadLocal2 57 * after remove : threadLocal1 : null 58 * after remove : threadLocal2 : null 59 * */ 60 61 /* 62 * 每个thread下存有一个 ThreadLocal.ThreadLocalMap threadLocals, threadLocals中存放着threadLocal1、threadLocal2、threadLocal3、....,每一个threadLocal以键值对形式存在 63 * 线程局部变量,各个线程之间独立 64 * 需手动remove,否则若线程一直存在时,将导致内存泄漏 65 * */ 66 67 /* 68 * 对于初始化值,第一次调用get方法访问该值时调用初始化方法,但若在get之前调用了set方法,则不会再调用初始化方法。 69 * 正常情况下初始化方法只会被调用一次,但如果remove了,则下次get时还会再调用一次初始化方法 70 * https://www.jianshu.com/p/73a1c128c5d9 71 * */
-- ThreadLocal的静态内部类ThreadLocalMap为每一个Thread都维护了一个数组table。ThreadLocal通过数组下标,将不同value存储到对应的位置。
-- 一个Thread只持有一个ThreadLocalMap,所以ABCD对应同一个ThreadLocalMap,ABCD存储在数组的不同位置。
1 public class ApplicationDemo {
2 //每一个线程,都分别存在ABCD四个线程局部变量
3 public static ThreadLocal<String> localVarA = new ThreadLocal<>();
4 public static ThreadLocal<String> localVarB = new ThreadLocal<>();
5 public static ThreadLocal<String> localVarC = new ThreadLocal<>();
6 public static ThreadLocal<Integer> localVarD= new ThreadLocal<>();
7
8 public static void main(String[] args){
9 }
10 }
-- 总结如下:
- 对于某一ThreadLocal来讲,他的索引值i是确定的,在不同线程访问时访问的是不同的table数组的同一位置即都为table[i],只不过这个不同线程之间的table是独立的。
- 对于同一线程的不同ThreadLocal来讲,这些ThreadLocal实例共享一个table数组,然后每个ThreadLocal实例在table中的索引i是不同的。
-- remove()方法判断某一线程的某个线程局部变量是否为null,不为空则删除该线程局部变量。(每个线程的线程局部变量存放在自己的本地内存变量ThreadLocals中,若该线程不消亡,则线程局部变量就会一直存在,可能导致内存溢出,因此用毕需要及时remove掉)
-- ThreadLocal类是不支持继承的,即父线程设置的值,子线程无法获取。想要支持继承的需要使用InheritableThreadLocal类
(原文参考:https://www.jianshu.com/p/3c5d7f09dfbd)
(原文参考:https://www.cnblogs.com/fsmly/p/11020641.html)
集中起来的意志可以击穿顽石

浙公网安备 33010602011771号