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)

 

posted @ 2020-10-18 01:55  α_伊卡洛斯  阅读(225)  评论(0)    收藏  举报