ThreadLocal线程变量
首先看下ThreadLocal的set()方法存数据的过程,首先获取当前的线程中保持的ThreadLocalMap,每个线程的ThreadLocalMap都是不一样的,因此存储的值是不同的。
public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {map.set(this, value);} else {createMap(t, value);}}
如果在一个线程中首次使用ThreadLocal保持数据,则需要创建ThreadLocalMap,ThreadLocalMap中保存数据的实体是Entry,保存数据的过程就是先计算这个ThreadLocal对象的hashcode,根据hashcode计算在Entry数组中的位置,然后将创建的Entry保存在这个位置。
void createMap(Thread t, T firstValue) {t.threadLocals = new ThreadLocalMap(this, firstValue);}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);}
如果在第一次之后使用ThreadLocal的话,则根据ThreadLocal计算hashcode,再根据hashcode计算Entry数组的索引,根据索引找到这个线程对应的Entry,如果是当前线程使用的ThreadLocalif (k == key),则将对象设置进来,即写到存储数据的Entry中。
private void set(ThreadLocal<?> key, Object value) {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);return;}}tab[i] = new Entry(key, value);int sz = ++size;if (!cleanSomeSlots(i, sz) && sz >= threshold)rehash();}
当通过get()方法获取数据时,首先找到当前的线程对象,获取线程对象内部的ThreadLocalMap,然后根据ThreadLocal对象计算Entry的索引,找到本线程存储数据的Entry,获取Entry中的数据。
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();}private Entry getEntry(ThreadLocal<?> key) {int i = key.threadLocalHashCode & (table.length - 1);Entry e = table[i];if (e != null && e.get() == key)return e;elsereturn getEntryAfterMiss(key, i, e);}
- ThreadLocal内存泄漏的问题
可以看到Entry是指向ThreadLocal的弱引用,弱引用不会阻止gc的垃圾回收,如果这个ThreadLocal对象置为null,指向ThreadLocal对象的弱引用不会阻止gc的垃圾回收,此时ThreadLocal对象存在但是无法访问,通过get()方法获取value时需要计算ThreadLocal对象的hashcode,在ThreadLocal对象被回收的情况就无法计算hashcode,也就无法访问这个value引用的对象,造成内存泄漏了。
static class Entry extends WeakReference<ThreadLocal<?>> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}
解决方法:
- 将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用,可以通过ThreadLocal对象访问到保存的数据,不会造成内存泄漏
- 调用remove()方法清除内存
public void remove() {ThreadLocalMap m = getMap(Thread.currentThread());if (m != null) {m.remove(this);}}private void remove(ThreadLocal<?> key) {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)]) {if (e.get() == key) {e.clear();expungeStaleEntry(i);return;}}}
相关文章:
ThreadLocal线程变量
首先看下ThreadLocal的set()方法存数据的过程,首先获取当前的线程中保持的ThreadLocalMap,每个线程的ThreadLocalMap都是不一样的,因此存储的值是不同的。 public void set(T value) {Thread t Thread.currentThread();ThreadLocalMap map …...
【linux安装redis详解】小白如何安装部署redis,linux安装部署只需5步骤(图文结合,亲测有效)
【写在前面】前端时间接触了一下redis,也是迫于页面查询响应太慢,没办法听说redis这个可持久化内存数据库,于是乎便想着在自己的机器上安装一套,接下来就重点和大家说说怎么从小白开始摸索redis 目录1、下载2、安装2.1 创建文件存…...
2023只会“点点点”,被裁只是时间问题,高薪的自动化测试需要掌握那些技能?
互联网已然是存量市场了,对人员规模的需求正在放缓。在存量市场里,冗余人员和低效人员会被淘汰、被外包。而优秀的人才也会一直受到招聘方的青睐。所以我们就看到了近期行业里冰火两重天的一幕,一边是大量的低端测试工程师被淘汰、求职屡屡碰…...
C语言【柔性数组】
柔性数组🫅什么是柔性数组🫅柔性数组的使用🫅柔性数组的优势🫅什么是柔性数组 也许你从来没有听说过柔性数组(flexible array)这个概念,但是它确实是存在的。 C99 中,结构中的最后一…...
AcWing275. 传纸条
AcWing275. 传纸条小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排坐成一个 m行 n 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的…...
圆角矩形的绘制和曲线均匀化
摘要: 圆角矩形是软件 UI 等视觉设计中的常见表达,一种常见的绘制方法是将矩形的四角替换为与边相切的四分之一圆弧,然而这种绘制方式会在连接处产生视觉上的切折感,这是因为圆弧和直线的连接处只满足 G1G^1G1 连续性。本文探究了…...
【Linux】环境变量,命令行参数,main函数三个参数保姆教学
目录 ☃️1.奇奇怪怪的现象和孤儿进程 ☃️2.环境变量 ☃️3.深刻理解main函数的前两个参数和命令行参数 ☃️1.奇奇怪怪的现象和孤儿进程 首先回顾一下之前我们学过的fork()创建子进程 fork(void)的返回值有两种 注意fork()头…...
美国访问学者生活中有哪些饮食文化特点?
美国的教育毋庸置疑,排在世界数一数二的位置,美食美景更是数不胜数,那么他们有哪些饮食习惯,下面51访学网小编为你们详细介绍这些内容吧。 一、美国饮食文化特点 1、美国的饮食文化体现科学、适度、快捷,以满足人体的…...
RxJava中的Subject
要使用Rxjava首先要导入两个包,其中rxandroid是rxjava在android中的扩展 implementation io.reactivex:rxandroid:1.2.1implementation io.reactivex:rxjava:1.2.0Subject Subject 既可以是一个 Observer 也可以是一个 Observerable,它是连接 Observer 和…...
vue-element-admin在git 上 clone 之后无法install
一. 无法install的原因因为vue-element-admin引入的富文本编辑插件所导致 由于tui-editor变更 名字 导致 依赖查询找不到对应的版本二. 解决的办法先删掉package.json中tui-editor:1.3.3找到 \src\components\MarkdownEditor\index.vue 把所有的import 替换成下面4个import cod…...
Linux线程调度实验
Linux线程调度实验 1.获取线程属性 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <pthread.h> #include <time.h> #include <stdlib.h> #include <errno.h> #define _GNU_SOURCE#define handle_error…...
洛谷P5735 【深基7.例1】距离函数 C语言/C++
【深基7.例1】距离函数 题目描述 给出平面坐标上不在一条直线上三个点坐标 (x1,y1),(x2,y2),(x3,y3)(x_1,y_1),(x_2,y_2),(x_3,y_3)(x1,y1),(x2,y2),(x3,y3),坐标值是实数,且绝对值不超过 100.00,求围成的三角形周长。保留两位…...
企业什么要建设自有即时通讯软件系统
随着科技的不断发展,各种即时通讯软件也不断发展进步,而这也与企业的发展息息相关,因为每个人,每个企业都有属于自己的机密,属于自己的隐私。 钉钉,企业微信,等公有的即时通讯软件给企业带来便利…...
LocalDNS
目录 文章目录目录本节实战DNS优化1、dns 5s 超时问题解决办法2、NodeLocal DNSCache实验软件关于我最后本节实战 实战名称💘 实战:NodeLocal DNSCache-2022.7.30(测试成功)💘 实战:NodeLocal DNSCache-2023.2.21(测试成功) DNS优…...
线程池种类和拒绝策略
1、newCachedThreadPool():可缓存的线程池,核心线程数量为0,最大线程数量为INT_MAX。线程空闲时间超过60秒被回收。适合处理大量小任务。 2、newFixedThreadPool()。固定线程个数的线程池,线程都是核心线程,没有应急线…...
Python制作9行最简单音乐播放器?不,我不满足
嗨害大家好鸭~我是小熊猫 好久不见啦~这次就来给大家整个大福利 ~ 源码资料电子书:点击此处跳转文末名片获取 最简单的9行代码音乐播放器如下: import time import pygamefile r歌曲路径 pygame.mixer.init() print(正在播放,file) track pygame.mixer.music.lo…...
零基础小白如何学会数据分析?
随着数字经济、大数据时代的发展,数据已然成为当下时代最重要的盈利资源,让企业在做决策和计划方案时更有针对性和依据,能提前预测市场发展方向,做好布局。由此而产生的数据分析岗位也逐渐被更多企业重视,特别是中大型…...
【Linux】vim的使用及常用快捷键(不会使用vim?有这篇文章就够了)
🔥🔥 欢迎来到小林的博客!! 🛰️博客主页:✈️小林爱敲代码 🛰️欢迎关注:👍点赞🙌收藏✍️留言 目录💖vim的基本概念vi…...
刷完这19道leetcode二分查找算法,不信进不了大厂
对于二分题,其实就是设定一个中间值 mid, 然后通过这个值进行一个判断 check(mid), 通过这个函数的返回值,判断将不可能的一半剪切掉; 在刷题的时候需要注意主要是两部分,check 函数的定义以及边界的选择(…...
四、Plugin Request and Sometimes pads
Request and Sometimes pads 到目前为止,我们只处理了总是可用的pad。然而,也有一些pad仅在某些情况下创建,或者仅在应用程序请求pad时创建。第一个有时被称为a;第二个被称为请求pad。pad的可用性(always, sometimes or request)可以在pad的…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
