ThreadLocal的使用方法:
ThreadLocal<Object> threadLocal = new ThreadLocal<Object>();
threadLocal.set("hello");
threadLocal.set("world");//同一个ThreadLocal对象多次调用set方法,后者会覆盖前者
threadLocal.get();//输出“world”
ThreadLocal原理总结:
1. Thread类中有一个ThreadLocal.ThreadLocalMap成员变量,这是线程能够保存私享数据的原因,线程间不共享数据。
2.调用set方法,获取当前线程并根据当前线程获取当前线程的ThreadLocalMap成员变量。
3.如果Thread类中ThreadLocalMap成员变量不存在则使用new关键字创建,如果当前线程存在拿来使用。
4.ThreadLocalMap调用set(ThreadLocal<?>,value)时,首先将参数中的ThreadLocal对象进行int i = key.threadLocalHashCode & (len-1); ,从Entry[]数组中检查索引值为i的Entry对象,不存在则创建Entry对象并放在数组中保存。
5.如果存在,首先检查key值即ThreadLocal实例对象与Entry[]中的值是否相同,如果相同就改变对应的value,如果不同继续在数组中查找,如果查找不到就建立新的Entry对象放到数组中。
6.值得一提的是Entry类它继承于WeakReference<ThreadLocal<?>>类,保存的key是ThreadLocal<?>对象,value是Object,因为是弱引用当GC扫描的时候它的key会被系统回收,如果value被外部引用却不可以被回收,有可能会造成内存泄漏,所以ThreadLocal使用结束要记得调用ThreadLocal.remove()方法,及时释放内存。
7.思考:为什么ThreadLocalMap内部要使用Entry数组呢?因为尽管每个ThreadLocal实例对象中只能保存一个值,多次调用set方法会覆盖,但是一个线程却可以创建并使用多个ThreadLocal对象,每个ThreadLocal对象对应Entry[]数组中的元素。
网友评论