Thread
ThreadLocalMap(ThreadLocal内部实现的Map)
table:ThreadLocal.ThreadLocalMap.Entry[] // 一个线程可对应多个ThreadLocal
Entry类(继承WeakReference,父类构造key让key成弱引用)
Entry(ThreadLocal<?> k, Object v)
ThreadLocal(可当成工具类)
get()、set()、remove()方法,操作ThreadLocalMap,包括对Thread的ThreadLocalMap进行初始化
get()过程:取出当前线程的ThreadLocalMap,计算该ThreadLocal在Entry[]中的下标然后获取Entry的value。
关于弱引用:
1.前提:因为Entry存值的算法原因,需要对比key是否一致,所以Entry需要保存key。key可以简单理解成ThreadLocal。
2.key不用强引用是因为在线程中将ThreadLocal置为null后,如果ThreadLocalMap中的Entry还有ThreadLocal的强引用会导致内存泄漏。所以当内存不足gc时并不会回收key对象,因为还存在new ThreadLocal()的强引用。
3.key的弱引用解决了ThreadLocal不会发生内存泄漏的问题。
ThreadLocal使用补充:
1.一般使用static修饰,避免重复创建导致浪费(可当成工具类)
2.InheritableThreadLocal可以使父线程生成的变量传递到子线程中进行使用,thread中维护两个
ThreadLocalMap,一个是threadLocals,一个是inheritableThreadLocals,当父线程创建子线程时,会把本线程的inheritableThreadLocals的值赋给子线程的inheritableThreadLocals
关于内存泄漏:
1.ThreadLocalMap中Entry的value是强引用,当ThreadLocal被回收后如果线程还未被回收就会发生内存泄漏。(value在线程中,但是无法通过key去访问了。)
2.set()、get()、remove()方法的时候,会清理掉key为null的记录。
3.避免内存泄露方法就是不使用时remove掉。
前提说明:只要这个线程对象被gc回收,就不会出现内存泄露。但在threadLocal设为null和线程结束这段时间不会被回收的,就发生了我们认为的内存泄露。另外,线程复用,清空ThreadLocal时会出现内存泄露。