记录一下 threadlocal 发现再不记录的话就要忘掉了
首先threadlocal 在哪里吧
thread 里
ThreadLocal.ThreadLocalMap threadLocals = null;
但如果你直接从 thread 里能得到吗
并不能 Thread.currentThread().得不到
只记录 threadlocal的知识的话其实并没有什么意义吧感觉 结合应用场景去让自己理解threadlocal
网上说的threadlocal 的用途 :说可以用在 数据库 的线程池中 起到隔离 每个线程链接不一样的作用
或者 http 中的 session 也是,当时我对session 也很有疑惑,session 是服务端的技术,然后的话,
我当时就在想为什么 比如我这个用户往session 里放数据对吧,然后前端可以取到。
那我只要一个用户向session 存放了数据,别的用户 就完全可以${session.value} 完全可以取到这个值啊,
那这完全不隔离啊,是不是因为这个原因,才有了model 或者 modelanview 这样的返回结果,存放的数据只对下一次有效。
但后来,网上的教程说,因为网上threadlocal 的讲知识的教程实在太多了,
在我看的 3y 大哥中的,
https://www.juejin.im/post/6844903586984361992 避免一些参数的传递的理解可以参考一下Cookie和Session
然后在想,cookie session 会话,是不是利用了 threadlocal 这个技术
实现的,因此所以就是说,我们的seesion 是不会被别人所访问的。因为tomcat 分配给每个用户的工作线程是不一样的,
后来想你的一次http 请求完成后 就失效了对吧, 但session 还是有的。
其实 之前就学过 session 和 cookie 都是根据 id 来确定要给哪个浏览器 传数据的,你的浏览器会话是一个id,再看一个网页就是另一个会话了
和 threadlocal 没有关系。
除了上面两个实际的东西,因为自己学过日志这块,会了解到mdc mdc 也是一个 InheritableThreadLocal 它是可以从父线程中继承value 的threadlocal
其实也是用到 threadlocal 这种思想。
还有被大家广泛写的 threadlocal 的内存泄漏问题,其实和弱引用没有什么关系,如果key 是强引用更会出现问题,如果是强引用的话,
这句话括号是 别人写的
{
key 使用强引用:引用的ThreadLocal的对象被回收了,但是ThreadLocalMap还持有ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,导致Entry内存泄漏。
key 使用弱引用:引用的ThreadLocal的对象被回收了,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。value在下一次ThreadLocalMap调用set,get,remove的时候会被清除。
官方文档的说法:
To help deal with very large and long-lived usages, the hash table entries use WeakReferences for keys.
为了处理非常大和生命周期非常长的线程,哈希表使用弱引用作为 key。
建议:
每次使用完ThreadLocal,都调用它的remove()方法,清除数据。
文章出处 现在在审核:
https://www.jianshu.com/p/a1cd61fa22da(原文) https://www.cnblogs.com/myseries/p/12081507.html
}
所以官方 就是考虑到了 threadlocal 和 threadlocalmap 与thread 的这种关系,才使用弱引用的。 而且官方想到了这个问题,就是在每次你
get set remove 的时候都会监测 key 是否为null 的 null 的话也将value 为null 去让value 被回收掉,所以这个问题多了解才知道。
学到现在的话,感觉对threadlocal 这种,对在一次http 请求内不同程序之间的存值和取值是相当有用的感觉,取到的都是这次请求内的,这也让我联想到
mdc 一次日志请求 打印的时间很短,所以很适合使用 threadlocal 记录。
因为自己用到的threadlocal 挺多的,各种日志实现的mdc 也是不一样的 logback 就是使用了threadlocal 而log4j 还是使用的 InheritableThreadLocal
然后看同事的自己写的 threadlocal 怎么去实现的, 还要promagent 这个框架的话也是使用到了 threadlocal 。
看一个 threadlocal 的 get操作
首先 得到当前线程 getMap 就是得到从当前线程中 ThreadLocalMap
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 getMap(Thread t) {
return t.threadLocals;
}
这个 threadlocalMap 是一个 threadlocal 的静态内部类
map 是靠 entry 来实现的,
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private Entry[] table;
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
实际看到 也是用一个 数组来实现的, 拉不拉链的话不很确定,但是估计一个线程存放的东西不像hashmap 的多。
而且 threadlocal 是一个线程内部的map 也不存在线程安全问题。
https://www.juejin.im/post/6844903586984361992
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。