介绍
ThreadLocal
提供线程局部变量,ThreadLocal实例通常是线程私有静态字段,使用的目的是希望将线程与状态关联起来。与JMM中局部变量有几分相似之处,但是不用写回主内存(如果违反,那就线程不安全),Thread用完要remove(),特别在线程池的情况下,会出现内存泄漏。
Thread、ThreadLocal、ThreadLocalMap
ThreadLocal.ThreadLocalMap 各自线程拥有自己的Map。
- 注意???
思考:为什么要在线程中使用ThreadLocalMap?为什么是Entry数组?
因为一个线程可以拥有多个ThreadLocal,没错,多个ThreadLocal变量。
强、软、弱、虚
强引用:普通对象引用。
Student a=new Student();
a=null;
软引用:内存足够时保留,内存不够时会回收
弱引用:只要gc就回收
虚引用:在对象回收后进行通知,放入引用队列。
什么是内存泄漏?
不再会被使用的对象,不能被回收。
为什么会出现内存泄漏?
key是弱引用,被回收后,value没有被回收。
threadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal不存在外部强引用时,Key(ThreadLocal)势必会被GC回收,这样就会导致ThreadLocalMap中key为null, 而value还存在着强引用,只有thead线程退出以后,value的强引用链条才会断掉。
但如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:
Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value
永远无法回收,造成内存泄漏。
仔细想想,ThreadLocal 下面这个设计值得学习
- Thead 线程中有ThreadLocalMap
- 在线程内创建ThreadLocal会自动放进ThreadLocalMap
ThreadLocal<String> threadLocal = new ThreadLocal<>();
threadLocal.set("123");
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = t.threadLocals;
if (map != null) {
map.set(this, value);
} else {
createMap(t, value);
}
}