threadlocal记录
时间:2022-07-25
本文章向大家介绍threadlocal记录,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
记录一下 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
- HDUOJ---------2255奔小康赚大钱
- HDUOJ------1711Number Sequence
- HDUOJ---1712 ACboy needs your help
- HDUOJ---1867 A + B for you again
- HDUOJ--------1420Prepared for New Acmer
- PowerVM虚拟化环境下 CPU 利用率的监控与探究
- 虚函数中构造函数的调用顺序
- HDUOJ-----4512吉哥系列故事——完美队形I(LCIS)
- go语言mongdb管道使用(二)
- HDUOJ--4565 So Easy!
- Go 语言Map(集合)
- 简单的java实验,涉及到 类继承以及接口问题,方法体的重写(区别于重载)
- java 快速求素数
- 狄斯奎诺(dijkstra 模板)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【笔记】《C++Primer》—— 第13章:拷贝控制
- 【笔记】《C++Primer》—— 第16章:模板与泛型编程
- 【笔记】《C++Primer》—— 第19章:特殊工具与技术
- 【翻译】C++14的新特性简介
- Python 为什么要有 pass 语句?
- 【翻译】C++17的新特性简介
- 各类SQL日期时间处理方法
- 这可能是最全最实用的Vim操作集合
- 个人珍藏的80道多线程并发面试题(1-10答案解析)
- 理解DOM Diff算法
- 腾讯云ES集群通过COS实现跨地域备份与恢复
- Thymeleaf一篇就够了
- python scipy.stats实现各种常见的统计分布
- 操作系统基础 - 文件系统
- Linux升级OpenSSH修复高危漏洞