
ThreadLocal是一种空间换时间的方法。
ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也即变量在线程间隔离而在方法或类间共享的场景。
ThreadLocal中填充的变量属于这个线程,对于其他线程是不可见的。
ThreadLocal提供了线程的局部变量,每个线程都可以通过set()和get()来对这个局部变量进行操作,但不会和其他线程的局部变量进行冲突,实现了线程的数据隔离。
ThreadLocal原理
1 |
|
1 |
public T get() { |
-
每个Thread维护着一个ThreadLocalMap的引用
-
ThreadLocalMap是ThreadLocal的内部类,用Entry来进行存储
-
调用ThreadLocal的set()方法时,实际上就是往ThreadLocalMap设置值,key是ThreadLocal对象,值是传递进来的对象
-
调用ThreadLocal的get()方法时,实际上就是往ThreadLocalMap获取值,key是ThreadLocal对象
-
ThreadLocal本身并不存储值,它只是作为一个key来让线程从ThreadLocalMap获取value,存储数据的还是ThreadLocalMap。
内存泄漏问题

ThreadLocalMap,key的引用是弱引用,value的引用是强引用。
当把threadlocal实例置为null以后,没有任何强引用指向threadlocal实例,所以threadlocal将会被gc回收. 但是,我们的value却不能回收,因为存在一条从current thread连接过来的强引用,这样就造成了内存泄露。只有当前thread结束以后, current thread就不会存在栈中,强引用断开, Current Thread, Map, value将全部被GC回收.
Java为了最小化减少内存泄露的可能性和影响,在ThreadLocal的get,set的时候都会清除线程Map里所有key为null的value。所以最怕的情况就是,threadLocal对象设null了,开始发生“内存泄露”,然后使用线程池,这个线程结束,线程放回线程池中不销毁,这个线程一直不被使用,或者分配使用了又不再调用get,set方法,那么这个期间就会发生真正的内存泄露。
所以,为了避免内存泄漏,每次使用完ThreadLocal,并且不会再使用她的时候,都调用它的remove()方法,清除数据。




近期评论