前言
ThreadLocal的特性和底层实现。
用法
1 | /* 声明ThreadLocal */ |
特性
不同线程对同一个ThreadLocal对象的操作是相互独立和隔离的,不会相互影响。
底层实现
我们看一下 ThreadLocal
类中最常用的几个方法:
Set
1 | public void set(T value) { |
Get
1 | public T get() { |
Remove
1 | public void remove() { |
上面三个函数一开头都用到了getMap()方法,我们来看一下:
1 | ThreadLocalMap getMap(Thread t) { |
非常简单,直接返回线程Thread对象中的threadLocals变量,我们来看一下Thread类:
1 | public class Thread implements Runnable { |
可以看到Thread类中确实有 ThreadLocalMap
实例,也就是说,每个线程中都有这么一张Map,再结合 Set
和 Get
方法,可以看出,这个Map中,各个条目以ThreadLocal实例为key,值为value来存储。
同一个ThreadLocal实例对不同Thread隔离,就是这么实现的。
此外值得注意的是,ThreadLocalMap中的key是弱引用,之所以是弱引用是因为:ThreadLocalMap是Thread类的成员,因此其生命周期是和Thread相同的,如果该map中的key是ThreadLocal实例,如果某个ThreadLocal实例用完不用了,但由于map中还有对该实例的引用,因此,GC不会回收该对象,就会导致内存泄露,而使用弱引用之后,当外部的强引用消失之后,只剩弱引用,就会被回收了。
1 | static class ThreadLocalMap { |
ThreadLocalMap中的value还是强引用,因此如果ThreadLocal不用了,还是要调用remove()方法。
使用场景
比如连接池应用,使用ThreadLocal可以保存连接。