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引用对象相同直接覆盖

posted on 2020-08-07 21:00  silyvin  阅读(365)  评论(0编辑  收藏  举报