public class ThreadLocalDemo {
private ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(()->0);
public void add(){
threadLocal.set(threadLocal.get()+1);
}
public Integer get(){
return threadLocal.get();
}
public static void main(String[] args) {
ThreadLocalDemo threadLocalDemo = new ThreadLocalDemo();
for (int i = 0; i < 2; i++) {
new Thread(()->{
while (true){
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadLocalDemo.add();
System.out.println(Thread.currentThread().getName()+":线程当前获取num值为:"+threadLocalDemo.get());
}
}).start();
}
}
}
class Thread implements Runnable {
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
}
public void set(T value){
//先获取当前线程实例(调用者线程)
Thread t = Thread.currentThread();
//先通过当前线程实例作为key去获取ThreadLocalMap
ThreadLocalMap map = getMap(t);
//如果获取不是null,直接set值,key为当前定义的ThreadLocal变量的this引用。
if(map !=null )
map.set(this,value);
//如果为null说明是首次添加,要先创建出对应的map
else
createMap(t,value);
}
getMap(Thread t)方法获取的是当前线程对应的threadLocals。
ThreadLocalMap getMap(Thread t){
//获取的是自己的线程变量threadLocals,并且绑定到调用线程的的成员变量threadLocals上。
return t.threadLocals;
}
如果调用getMap方法返回null,就直接将value值设置到threadLocals中(key为当前线程的引用,值为本地变量);如果getMap方法返回null说明是第一次调用set方法(因为threadLoclas默认值为null),这个时候就要调用createMap方法创建threadLocals。createMap方法不仅创建了threadLocals,同时也将本地变量添加到threadLocals中。
void createMap(Thread t,T firstValue){
t.threadLocals = new ThreadLocalMap(this,firstValue);
}
在get方法的实现中,首先获取当前调用者线程,如果当前线程的threadLocals不为null,就直接返回当前线程绑定的本地变量的值,否则执行setInitialValue方法初始化threadLocals变量。setInitialValue方法中,类似于set方法的实现,都是判断当前线程的threadLocals变量是否为null,是则添加本地变量(这个时候由于初始化,所以添加的值也为null),否则创建threadLocals变量,同样添加的值为null。
public T get(){
//获取当前线程实例
Thread t = Thread.currentThread();
//获取当前实例的ThreadLocalMap
ThreadLocalMap map = getMap(t);
//判断map是否为空
if(map != null){
//获取map中的value返回
ThreadLocalMap.Entry e = map.getEntry(this);
if(e != null){
T result = (T)e.value;
return result;
}
}
//如果map为空则调用setInitialValue进行初始化,设置threadLocals变量value设为null
return setInitialValue();
}
private T setInitialValue(){
//protected T initialValue() { return null; }
T value = initialValue();
//获取当前线程
Thread t = Thread.currentThread();
//以当前线程作为key值,查找对应的线程变量,找到对应的map
ThreadLocalMap map = getMap(t);
//如果map不为null
if(map != null)
//这块value 的值为null
map.set(this,value);
else
//这块value的值也为null
createMap(t,value);
return value;
}
remove方法源码分析
remove方法判断该当前线程对应的threadLocals变量是否为null,不为null就直接删除当前线程中指定的threadLocals变量。
public void remove(){
//获取当前线程绑定的threadLocals
ThreadLocalMap map = getMap(Thread.currentThread());
//如果map不为null,就移除当前线程中指定的ThreadLocal实例的本地变量
if(m != null){
m.remove(this);
}
}
每个线程内部都会有一个名为threadLocals的成员变量,该变量的类型为ThreadLocal.ThreadLocalMap类型,其中的key为当前定义的ThreadLocal变量的this引用,value为我们使用set方法设置的值,每个线程本地变量存放在自己的本地内存变量threadLocals中,如果当前线程一直不消亡,那么这些线程一直存在(所以会导致内存溢出),因此使用完毕后要将其remove掉。
public class ThreadLocalDemo {
private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
threadLocal.set("mainValue");
new Thread(()->{
System.out.println("子线程拿到threadLocal中的值:"+threadLocal.get());
}).start();
System.out.println("main线程拿到threadLocal中的值:"+threadLocal.get());
}
}
/**
* 是继承自WeakReference的一个类,该类中实际存放的key是
* 指向ThreadLocal的弱引用和与之对应的value值(该value值
* 就是通过ThreadLocal的set方法传递过来的值)
* 由于是弱引用,当get方法返回null的时候意味着坑能引用
*/
static class Entry extends WeakReference<ThreadLocal<?>> {
/** value就是和ThreadLocal绑定的 */
Object value;
//k:ThreadLocal的引用,被传递给WeakReference的构造方法
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
//WeakReference构造方法(public class WeakReference extends Reference )
public WeakReference(T referent) {
super(referent); //referent:ThreadLocal的引用
}
//Reference构造方法
Reference(T referent) {
this(referent, null);//referent:ThreadLocal的引用
}
Reference(T referent, ReferenceQueue<? super T> queue) {
this.referent = referent;
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}
Entry的源码中我们可以看出Entry继承WeakReference