new ThreadLocal后,一定会调用这个set方法,往里边存放值。
ThreadLocal.ThreadLocalMap threadLocals = null;
//可以看出这是一个静态内部类
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = t.threadLocals;
if (map != null)
//this就等于带用这个方法的实体对象(ThreadLoacl)
map.set(this, value);
else
threadLocals = new ThreadLocalMap(this, value);
//调用下面的构造方法,构造方法将key value存入
}
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[16];
int i = firstKey.threadLocalHashCode & 15;
table[i] = new Entry(firstKey, firstValue);
size = 1;
//下面我也不知道,不管他。
setThreshold(INITIAL_CAPACITY);
}
,当你想取出的时候,调用get就可得到 可以看出就是用this当前对象取getEntry()得到的。
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;
}
}
return setInitialValue();
}
总结:一个线程等于一个人,threadlocalmap等于这人身上的很多口袋,set时,将一个value放入指定口袋,这个线程到任何地方都可以指定口袋得到这个值。
使用场景:jdbc在对数据库操作时,一个业务层调用多个dao层的sql,一个sql对应一个connection,开始事务的时候会一个sql都有自己的事务,无法,一个sql错误就全部回滚。用threadlocal装一个共同的connection,可以做到哦。
注意:使用完该值后使用remove方法移除,否则线程池使用会造成内存泄漏,最终溢出。