ThreadLocal内存泄漏问题实践(三)非静态threadlocal
结论:
1 借助非静态threadlocal对象,实现多数据源的事务控制,threadlocal<Connection>与session对象绑定,每个数据源一个session对象注入ioc
2 threadlocal对象,没有equals方法,直接用==判断是否map同一个key
在mybatis Guice 事务源码解析中,我们观察到SqlSessionManager有个threadlocalsession,设置为非静态threadlocal对象
引起注意,做个实验:
/**
* https://www.cnblogs.com/silyvin/articles/13455224.html
* Created by joyce on 2020/8/7.
*/
public class TestThreadLocalStatic {
private static ThreadLocal<Integer> staticThreadLocal = new ThreadLocal<>();
private ThreadLocal<Integer> nonStaticThreadLocal = new ThreadLocal<>();
private Integer integer;
public TestThreadLocalStatic(Integer integer) {
this.integer = integer;
}
public static void main(String f[]) {
new TestThreadLocalStatic(2).setThreadLocal();
new TestThreadLocalStatic(3).getThreadLocal();
}
public void setThreadLocal() {
staticThreadLocal.set(this.integer);
System.out.println(staticThreadLocal.hashCode());
nonStaticThreadLocal.set(this.integer);
System.out.println(nonStaticThreadLocal.hashCode());
}
public void getThreadLocal() {
System.out.println(staticThreadLocal.get());
System.out.println(staticThreadLocal.hashCode());
System.out.println(nonStaticThreadLocal.get());
System.out.println(nonStaticThreadLocal.hashCode());
}
/**
* 第1个对象的nonStaticThreadLocal hash为在线程threadlocalmap上x位
* 第2个对象的nonStaticThreadLocal hash为在线程threadlocalmap上y位
* 适用于希望一个类的不同对象有不同的threadlocal可以用,有不同的线程内值,比如多数据源
*/
}
输出:
1023892928
558638686
2
1023892928
null
1149319664
threadlocal作为key,同一个类的非静态threadlocal为不同对象,自然在map上不同槽位
静态threadlocal所有对象都共享一个,自然在map上相同位置
同时注意到,ThreadLocal类没有equels方法,那么怎么判断同一对象?
ThreadLocal.ThreadlocalMap:
private void set(ThreadLocal<?> key, Object value) {
// We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not.
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal<?> k = e.get();
if (k == key) {
e.value = value;
return;
}
if (k == null) {
replaceStaleEntry(key, value, i); ThreadLocal内存泄漏问题实践(二)中清理key为null(因为弱引用)的value
return;
}
}
首先取hash值,static threadlocal 是同一个对象,hash一样,non static threadlocal不是同一个对象,按Threadlocal hash规则肯定也不相同
可以看到直接用==判断,key引用对象相同直接覆盖