public class ThreadLocalDemo { static ThreadLocal二、ThreadLocal源码分析localVar = new ThreadLocal<>(); static void print(String str) { //打印--当前线程--中本地内存中本地变量的值 System.out.println(str + localVar.get()); //清除本地内存中的--当前线程--本地变量 localVar.remove(); } public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { //设置线程1中本地变量的值 localVar.set("线程1"); int a = 1; //调用打印方法 print("thread t1: "); //打印本地变量 print里面已经remove System.out.println("删除后 : " + localVar.get()); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { //设置线程1中本地变量的值 localVar.set("线程2"); //调用打印方法 print("thread t2: "); //打印本地变量 print里面已经remove System.out.println("删除后 : " + localVar.get()); } }); t1.start(); t2.start(); } }
ThreadLocal的set方法,实际是往实际调用的当前线程Thread的 ThreadLocalMap 类型的变量threadLocals里面 set key为 当前 ThreadLocal,value为当前set的值。
ThreadLocal源码分析:
public void set(T value) { //取当前实际调用的线程 Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); //如果map不为null,开始set值,key为当前定义的ThreadLocal变量的this引用,值为添加的本地变量值 if (map != null) map.set(this, value); else createMap(t, value); } ThreadLocalMap getMap(Thread t) { //返回Thread类下的定义的 ThreadLocal.ThreadLocalMap threadLocals return t.threadLocals; }
ThreadLocal类get方法,类似Map的方式,源码如下:
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); } private T setInitialValue() { T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; }三、父子线程间变量传递问题
同一个ThreadLocal变量在父线程中被设置值后,在子线程中是获取不到的。因为threadLocals为当前调用线程对应的本地变量,所以二者是不能共享的。
那子线程如何访问父线程的本地变量呢,可以使用InheritableThreadLocal类。InheritableThreadLocal类继承了ThreadLocal类,并重写了childValue、getMap、createMap三个方法。
使用示例:
public class InheritableThreadLocalDemo { private static InheritableThreadLocalthreadLocal = new InheritableThreadLocal<>(); public static void main(String[] args) { threadLocal.set("主线程变量"); System.out.println("value main:"+threadLocal.get()); Thread thread = new Thread(new Runnable() { @Override public void run() { String value = threadLocal.get(); System.out.println("value child:"+value); } }); thread.start(); } }
输出结果:
value main: 主线程变量
value child: 主线程变量
ThreadLocalMap中的Entry的key使用的是ThreadLocal对象的弱引用,在没有其他地方对ThreadLocal依赖,ThreadLocalMap中的ThreadLocal对象就会被回收掉,但是对应的不会被回收,这个时候Map中就可能存在key为null但是value不为null的项,所以,在实际的时候使用完毕后要及时调用remove方法避免内存泄漏。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)