ThreadLocal本质
2018-07-18 本文已影响138人
江江的大猪
无数的书籍、文章资料在讲ThreadLocal的时候从ThreadLocal切入,这样很难理解ThreadLocal到底是什么,最后很容易把ThreadLocal当做一个存放线程独立数据的容器,这就完全错了
从Thread类切入
- Thread内部有一个ThreadLocalMap的成员变量,里面存放着和这个线程绑定的数据。虽然ThreadLocalMap叫map,但是并没有实现map接口,只是提供了几个和map接口一样的方法,ThreadLocal作为ThreadLocalMap的key,所以说ThreadLocal本身并不存放数据,数据都在Thread对象中的ThreadLocalMap里,ThreadLocal只是从ThreadLocalMap中存取的key。可以将Thread看做一个域对象,就和java web中的四大域对象一样。
引用分析
-
entry里的key用Threadlocal的弱引用只能保证作为key的threadlocal对象不会内存泄漏,如果是强引用的话,使用的是线程池中的核心线程,那么该线程就会一直存在,Threadlocal 对象就永远得不到释放,发生内存泄漏。
-
Threadlocal源码中的注释说了,Threadlocal适合作为private static的静态属性,所以弱引用只是为了避免使用非静态Threadlocal造成的Threadlocal内存泄漏
-
ThreadLocal的内存泄漏指的是entry中的value泄露,作为key的Threadlocal肯定不会泄露
-
ThreadLocal不会发生内存泄漏的两个条件满足一个即可,一个是保证调用remove,或者保证线程结束
-
set get方法都对key为null(发生了gc,作为key的ThreadLocal被回收了)的entry做了处理,避免内存泄漏
Threadlocal使用场景
- 数据库连接池中每一个线程都持有一个数据库连接。app的后端工程中一般会封一个组件,每个请求的线程都持有当前用户的ip、版本号什么的