当前位置: 首页 > news >正文

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;}}

解决方法:

  1. 将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用,可以通过ThreadLocal对象访问到保存的数据,不会造成内存泄漏
  2. 调用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()方法存数据的过程&#xff0c;首先获取当前的线程中保持的ThreadLocalMap&#xff0c;每个线程的ThreadLocalMap都是不一样的&#xff0c;因此存储的值是不同的。 public void set(T value) {Thread t Thread.currentThread();ThreadLocalMap map …...

【linux安装redis详解】小白如何安装部署redis,linux安装部署只需5步骤(图文结合,亲测有效)

【写在前面】前端时间接触了一下redis&#xff0c;也是迫于页面查询响应太慢&#xff0c;没办法听说redis这个可持久化内存数据库&#xff0c;于是乎便想着在自己的机器上安装一套&#xff0c;接下来就重点和大家说说怎么从小白开始摸索redis 目录1、下载2、安装2.1 创建文件存…...

2023只会“点点点”,被裁只是时间问题,高薪的自动化测试需要掌握那些技能?

互联网已然是存量市场了&#xff0c;对人员规模的需求正在放缓。在存量市场里&#xff0c;冗余人员和低效人员会被淘汰、被外包。而优秀的人才也会一直受到招聘方的青睐。所以我们就看到了近期行业里冰火两重天的一幕&#xff0c;一边是大量的低端测试工程师被淘汰、求职屡屡碰…...

C语言【柔性数组】

柔性数组&#x1fac5;什么是柔性数组&#x1fac5;柔性数组的使用&#x1fac5;柔性数组的优势&#x1fac5;什么是柔性数组 也许你从来没有听说过柔性数组&#xff08;flexible array&#xff09;这个概念&#xff0c;但是它确实是存在的。 C99 中&#xff0c;结构中的最后一…...

AcWing275. 传纸条

AcWing275. 传纸条小渊和小轩是好朋友也是同班同学&#xff0c;他们在一起总有谈不完的话题。一次素质拓展活动中&#xff0c;班上同学安排坐成一个 m行 n 列的矩阵&#xff0c;而小渊和小轩被安排在矩阵对角线的两端&#xff0c;因此&#xff0c;他们就无法直接交谈了。幸运的…...

圆角矩形的绘制和曲线均匀化

摘要&#xff1a; 圆角矩形是软件 UI 等视觉设计中的常见表达&#xff0c;一种常见的绘制方法是将矩形的四角替换为与边相切的四分之一圆弧&#xff0c;然而这种绘制方式会在连接处产生视觉上的切折感&#xff0c;这是因为圆弧和直线的连接处只满足 G1G^1G1 连续性。本文探究了…...

【Linux】环境变量,命令行参数,main函数三个参数保姆教学

目录 ☃️1.奇奇怪怪的现象和孤儿进程 ☃️2.环境变量 ☃️3.深刻理解main函数的前两个参数和命令行参数 ☃️1.奇奇怪怪的现象和孤儿进程 首先回顾一下之前我们学过的fork&#xff08;&#xff09;创建子进程 fork(void)的返回值有两种 注意fork&#xff08;&#xff09;头…...

美国访问学者生活中有哪些饮食文化特点?

美国的教育毋庸置疑&#xff0c;排在世界数一数二的位置&#xff0c;美食美景更是数不胜数&#xff0c;那么他们有哪些饮食习惯&#xff0c;下面51访学网小编为你们详细介绍这些内容吧。 一、美国饮食文化特点 1、美国的饮食文化体现科学、适度、快捷&#xff0c;以满足人体的…...

RxJava中的Subject

要使用Rxjava首先要导入两个包&#xff0c;其中rxandroid是rxjava在android中的扩展 implementation io.reactivex:rxandroid:1.2.1implementation io.reactivex:rxjava:1.2.0Subject Subject 既可以是一个 Observer 也可以是一个 Observerable&#xff0c;它是连接 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​)&#xff0c;坐标值是实数&#xff0c;且绝对值不超过 100.00&#xff0c;求围成的三角形周长。保留两位…...

企业什么要建设自有即时通讯软件系统

随着科技的不断发展&#xff0c;各种即时通讯软件也不断发展进步&#xff0c;而这也与企业的发展息息相关&#xff0c;因为每个人&#xff0c;每个企业都有属于自己的机密&#xff0c;属于自己的隐私。 钉钉&#xff0c;企业微信&#xff0c;等公有的即时通讯软件给企业带来便利…...

LocalDNS

目录 文章目录目录本节实战DNS优化1、dns 5s 超时问题解决办法2、NodeLocal DNSCache实验软件关于我最后本节实战 实战名称&#x1f498; 实战&#xff1a;NodeLocal DNSCache-2022.7.30(测试成功)&#x1f498; 实战&#xff1a;NodeLocal DNSCache-2023.2.21(测试成功) DNS优…...

线程池种类和拒绝策略

1、newCachedThreadPool()&#xff1a;可缓存的线程池&#xff0c;核心线程数量为0&#xff0c;最大线程数量为INT_MAX。线程空闲时间超过60秒被回收。适合处理大量小任务。 2、newFixedThreadPool()。固定线程个数的线程池&#xff0c;线程都是核心线程&#xff0c;没有应急线…...

Python制作9行最简单音乐播放器?不,我不满足

嗨害大家好鸭~我是小熊猫 好久不见啦~这次就来给大家整个大福利 ~ 源码资料电子书:点击此处跳转文末名片获取 最简单的9行代码音乐播放器如下&#xff1a; import time import pygamefile r歌曲路径 pygame.mixer.init() print(正在播放,file) track pygame.mixer.music.lo…...

零基础小白如何学会数据分析?

随着数字经济、大数据时代的发展&#xff0c;数据已然成为当下时代最重要的盈利资源&#xff0c;让企业在做决策和计划方案时更有针对性和依据&#xff0c;能提前预测市场发展方向&#xff0c;做好布局。由此而产生的数据分析岗位也逐渐被更多企业重视&#xff0c;特别是中大型…...

【Linux】vim的使用及常用快捷键(不会使用vim?有这篇文章就够了)

&#x1f525;&#x1f525; 欢迎来到小林的博客&#xff01;&#xff01;       &#x1f6f0;️博客主页&#xff1a;✈️小林爱敲代码       &#x1f6f0;️欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 目录&#x1f496;vim的基本概念vi…...

刷完这19道leetcode二分查找算法,不信进不了大厂

对于二分题&#xff0c;其实就是设定一个中间值 mid, 然后通过这个值进行一个判断 check(mid)&#xff0c; 通过这个函数的返回值&#xff0c;判断将不可能的一半剪切掉&#xff1b; 在刷题的时候需要注意主要是两部分&#xff0c;check 函数的定义以及边界的选择&#xff08;…...

四、Plugin Request and Sometimes pads

Request and Sometimes pads 到目前为止&#xff0c;我们只处理了总是可用的pad。然而&#xff0c;也有一些pad仅在某些情况下创建&#xff0c;或者仅在应用程序请求pad时创建。第一个有时被称为a;第二个被称为请求pad。pad的可用性(always, sometimes or request)可以在pad的…...

PHP开发者必看:通过xss-labs靶场level1-10,彻底搞懂htmlspecialchars()的坑与正确用法

PHP开发者实战指南&#xff1a;从xss-labs靶场剖析htmlspecialchars()的深层防御逻辑 在Web安全领域&#xff0c;XSS漏洞长期占据OWASP Top 10榜单&#xff0c;而PHP作为服务端主力语言&#xff0c;其内置的htmlspecialchars()函数常被开发者视为防御利器。但真实情况是&#x…...

【技术选型指南】Avalonia、MAUI、Uno Platform、Flutter、Electron、Qt与Tauri:从场景到决策的深度剖析

1. 跨平台框架选型的核心考量因素 当你准备启动一个新项目或重构现有技术栈时&#xff0c;面对琳琅满目的跨平台框架&#xff0c;选择困难症很容易发作。我经历过多次这样的技术决策过程&#xff0c;发现关键在于先明确项目的核心需求。就像装修房子前要先确定是想要北欧简约风…...

轨道桥梁与列车这对CP,到底怎么互相伤害

车桥耦合动力学模型&#xff0c;轮轨耦合动力学模型&#xff0c;采用二自由度列车模型&#xff0c;可以改为FF梁SF梁&#xff0c;采用德国轨道谱&#xff0c;采用积分算法&#xff0c;可以输出桥梁任意位置的响应。玩轨道桥梁动力学的老铁们都知道&#xff0c;车桥耦合这玩意儿…...

如何让AI创作速度提升3倍?智能缓存技术TeaCache的完整指南

如何让AI创作速度提升3倍&#xff1f;智能缓存技术TeaCache的完整指南 【免费下载链接】ComfyUI-TeaCache 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-TeaCache 你是否曾为AI图像和视频生成的速度而烦恼&#xff1f;看着进度条缓慢移动&#xff0c;等待数分…...

广东省内推荐靠谱的知识产权服务机构

在广东省&#xff0c;随着创新驱动发展战略的深入实施&#xff0c;知识产权的重要性日益凸显。无论是企业还是个人&#xff0c;都越来越重视知识产权的保护和运用。选择一家靠谱的知识产权服务机构至关重要&#xff0c;它能为客户提供专业、高效的服务&#xff0c;助力客户在知…...

从零开始掌握Retrieval-based Voice Conversion WebUI:AI语音转换完整指南

从零开始掌握Retrieval-based Voice Conversion WebUI&#xff1a;AI语音转换完整指南 【免费下载链接】Retrieval-based-Voice-Conversion-WebUI 语音数据小于等于10分钟也可以用来训练一个优秀的变声模型&#xff01; 项目地址: https://gitcode.com/GitHub_Trending/re/Re…...

OpenClaw与Qwen3-VL:30B:高效个人AI办公助手实战

OpenClaw与Qwen3-VL:30B&#xff1a;高效个人AI办公助手实战 1. 为什么选择OpenClawQwen3-VL组合 去年冬天&#xff0c;当我第5次因为会议记录整理到凌晨两点时&#xff0c;终于决定寻找自动化解决方案。在尝试了市面上各种RPA工具后&#xff0c;偶然发现了OpenClaw这个开源框…...

PPTist:5分钟掌握专业级在线PPT制作,免费开源的高效演示解决方案

PPTist&#xff1a;5分钟掌握专业级在线PPT制作&#xff0c;免费开源的高效演示解决方案 【免费下载链接】PPTist 基于 Vue3.x TypeScript 的在线演示文稿&#xff08;幻灯片&#xff09;应用&#xff0c;还原了大部分 Office PowerPoint 常用功能&#xff0c;实现在线PPT的编…...

如何使用usearch进行水资源分配优化:用水数据的向量分析完整指南

如何使用usearch进行水资源分配优化&#xff1a;用水数据的向量分析完整指南 【免费下载链接】usearch Fastest Open-Source Search & Clustering engine for Vectors & &#x1f51c; Strings in C, C, Python, JavaScript, Rust, Java, Objective-C, Swift, C#, Go…...

如何快速实现Obsidian插件本地化:obsidian-i18n完整实践指南

如何快速实现Obsidian插件本地化&#xff1a;obsidian-i18n完整实践指南 【免费下载链接】obsidian-i18n 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-i18n 你是否曾因Obsidian插件全是英文界面而苦恼&#xff1f;作为中文用户&#xff0c;面对"Backli…...