ThreadLocal学习
前言
强引用 new出来的对象,相当于正常对象吧
软引用(softReference),用在缓存里面,空间不够主动被垃圾回收,用的时候重新load
new SoftReference(new Byte[1024*1024*10])
这个字节数组就是软引用;
弱引用(weakReference) 遇到gc就回收
new weakReference(new Byte[1024*1024*10]);
这个字节数组就是弱引用
threadlocal中用到了弱应用
threadlcoal,可以隔离线程变量,保证线程数据安全
每个线程都有一个map类型的成员变量:ThreadLocal.ThreadLocalMap threadLocals = null;
用来存放threadlocal以及其对应的值,这个threadLocals相当于线程内部全局变量,只要是这个线程哪里都可以使用,而别的线程不可用。
ThreadLocal的set方法就是把自己放入到threadLocals这个map中
//ThreadLocal的set方法
public void set(T value) {
Thread t = Thread.currentThread();
//下面有getMap(t)这个方法
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
ThreadLocal的get方法从threadLocals中获取到ThreadLocal对应的值
//ThreadLocal的get方法
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
//看源码可以知道返回的是null
return setInitialValue();
}
//获取到线程
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
//thread里面的成员变量
ThreadLocal.ThreadLocalMap threadLocals = null;
//ThreadLocal里的静态修饰的类
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
//被弱引用修饰,表明遇到GC就会被回收 super->WeakReference
super(k);
value = v;
}
}
-
spring中的声明式事务用了threadlocal保存connection保证是同一个connection操作数据库
-
由于线程池中的connection不会被释放,所以连接池中的线程中可能会包含上次任务中使用的value,因此线程池中使用threadlocal一定要remove,以免造成信息泄露等
-
由于threadlcoal是由WeakReference修饰的,所以ThreadLocalMap的key也就是threadlcoal,当threadlcoal的本地变量被清除后,再次遇到GC时,ThreadLocalMap中的threadlcoal就会被清除,但是value也是一个强引用,需要手动remove,以免遭成内存泄漏,引起内存溢出。
注:weakhashmap集合 中的key全是弱引用修饰的。
自己学习理解,不足之处请指正。