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

ThreadLocal

      • ThreadLocal
      • ThreadLocalMap
      • get
      • set
      • remove
        • 内存泄漏
            • key用强/弱引用
        • entry继承了弱引用

ThreadLocal

  • 一个对象的所有线程会共享其全局变量——>线程不安全

    解决方式:
    方式一:同步机制,加锁(时间换空间)
    方式二:ThreadLocal在每个线程中都创建了一个变量的副本,线程各自访问自己的副本变量,则不存在变量共享问题。(空间换时间)

    变量与线程的关系private static,所以ThreadLocal与线程的关系private static
    eg:session

  • 同一个线程内多个函数/组件间公共变量传递复杂,降低了多模块间的耦合度。关联线程和线程上下文

ThreadLocalMap

每一个thread都有一个threadLocalMap变量,key=threadLocal value=值
(一个thread可以有多个threadLocal)

public class Thread implements Runnable {//存储与此线程相关的threadLocal,值由threadLocal维护ThreadLocal.ThreadLocalMap threadLocals;
}

jdk1.7的实现方式为每一个threadLocal都有一个threadLocalMap变量,key=threadID value=值

  • 储存的entry减少,之前由thread数量决定,现在由threadLocal决定
  • thread销毁对应的threadLocalMap也销毁。threadLocalMap的生命周期=线程的生命周期,内存使用减少

get

在这里插入图片描述

private T get(Thread t) {ThreadLocalMap map = getMap(t);if (map != null) {if (map == ThreadLocalMap.NOT_SUPPORTED) {return initialValue();} else {//根据ThreadLocalHash计算index,取得Entry ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T) e.value;return result;}}}return setInitialValue(t);
}private T setInitialValue(Thread t) {T value = initialValue();ThreadLocalMap map = getMap(t);assert map != ThreadLocalMap.NOT_SUPPORTED;if (map != null) {map.set(this, value);} else {createMap(t, value);}if (this instanceof TerminatingThreadLocal<?> ttl) {TerminatingThreadLocal.register(ttl);}return value;
}

set

在这里插入图片描述

private void set(Thread t, T value) {ThreadLocalMap map = getMap(t);if (map == ThreadLocalMap.NOT_SUPPORTED) {throw new UnsupportedOperationException();}if (map != null) {map.set(this, value);} else {createMap(t, value);}
}//存入值
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)]) {if (e.refersTo(key)) {e.value = value;return;}if (e.refersTo(null)) {replaceStaleEntry(key, value, i);return;}}tab[i] = new Entry(key, value);int sz = ++size;if (!cleanSomeSlots(i, sz) && sz >= threshold)rehash();
}//初始化map
void createMap(Thread t, T firstValue) {t.threadLocals = new ThreadLocalMap(this, firstValue);
}

remove

private void remove(Thread t) {ThreadLocalMap m = getMap(t);if (m != null && m != ThreadLocalMap.NOT_SUPPORTED) {m.remove(this);}
}

内存泄漏

引用链:threadRef->thread->threadLocalMap<threadLocal,value>->entry->value

弱引用:如果这个对象只存在弱引用,那么在下一次GC时会被清理。

ThreadLocalMap 中使用的 key 为 ThreadLocal 的弱引用。所以如果 ThreadLocal 没有被外部强引用,在GC时ThreadLocal 会被清理掉,ThreadLocalMap中使用这个 ThreadLocal 的 key 也会被设为null。由于value 是强引用,不会被清理,依然存在,就会出现 key 为 null 的 value,value无法访问。在map中value为强引用不会被清除,直到map被清除。然而由于threadLocalMap的生命周期=线程,线程池通常采取线程复用的方法,所以线程池中的线程很难结束。所以value可能一直无法回收。
key=null

key用强/弱引用
  • key用强引用:引用ThreadLocal的对象被回收了,但threadLocalMap中还有threadLocal的强引用,若未手动删除,threadLocal不会被回收,导致entry内存泄漏
  • key用弱引用:引用ThreadLocal的对象被回收了,但threadLocalMap中还有threadLocal的弱引用,即使未手动删除,threadLocal也会被回收,导致value内存泄漏
  • 结论:若未手动删除key,都会导致内存泄漏。强引用threadLocal不会被回收,弱引用value。 内存泄漏与强/弱引用无关,根本原因在于threadLocalMap的生命周期=线程。

解决方式:用完threadLocal,调用remove清除无用的entry,由于Entry继承了弱引用类,会在下次GC时被JVM回收。get(),set(),remove(),会顺便移除key=null的entry

entry继承了弱引用

public class ThreadLocal<T> {static class ThreadLocalMap {private Entry[] table;//轻量级map,桶中存entry而非entry链表//Entry 继承弱引用static class Entry extends WeakReference<ThreadLocal<?>> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}}
}

相关文章:

ThreadLocal

ThreadLocalThreadLocalMapgetsetremove内存泄漏key用强/弱引用entry继承了弱引用ThreadLocal 一个对象的所有线程会共享其全局变量——>线程不安全 解决方式&#xff1a; 方式一&#xff1a;同步机制&#xff0c;加锁&#xff08;时间换空间&#xff09; 方式二&#xff1a…...

Java基础:JDK7-时间Date

JDK7以前时间相关类 1.Date Date date new Date(); , sout(date)得到的是现在所处位置的时间 Date date new Date(0L); , sout(date)得到的是时间原点也就是1970年1月1日08:00(东八区). date.setTime(1000L); sout(date)得到的是时间原点后一秒钟的时间 long time date.g…...

什么是IP地址?

IP协议中还有一个非常重要的内容&#xff0c;那就是给因特网上的每台计算机和其它设备都规定了一种地址&#xff0c;叫做“IP 地址”。由于有这种地址&#xff0c;才保证了用户在连网的计算机上操作时&#xff0c;能够高效而且方便地从千千万万台计算机中选出自己所需的对象来。…...

4年经验之谈,什么是接口测试?怎样做接口测试?

一、什么是接口&#xff1f;【文末学习资源分享】赶紧嫖&#xff01;冲&#xff01;&#xff01;&#xff01;&#xff01; 接口测试主要用于外部系统与系统之间以及内部各个子系统之间的交互点&#xff0c;定义特定的交互点&#xff0c;然后通过这些交互点来&#xff0c;通过…...

普通指针扫盲

一、什么是指针 C语言里&#xff0c;变量存放在内存中&#xff0c;而内存其实就是一组有序字节组成的数组&#xff0c;每个字节有唯一的内存地址。 CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位。这里&#xff0c;数据对象是指存储在内存 中的一个指定数据…...

深度学习笔记:神经网络权重确定初始值方法

神经网络权重不可为相同的值&#xff0c;比如都为0&#xff0c;因为如果这样网络正向传播输出和反向传播结果对于各权重都完全一样&#xff0c;导致设置多个权重和设一个权重毫无区别。我们需要使用随机数作为网络权重 实验程序 在以下实验中&#xff0c;我们使用5层神经网络…...

关于 python 的异常使用说明 (python 的文件和异常)

文章目录异常1. 处理异常 ZeroDivisionError 异常2. 使用 try-except 代码块3. 使用异常避免崩溃4. else 代码块5. 处理 FileNotFoundError 异常6. 分析文本7. 失败时一声不吭异常 pyhong 使用被异常成为异常的特殊对象来管理程序执行期间发生的错误。 每当发生让 python 不知所…...

Spark RDD持久化

RDD Cache缓存 RDD通过Cache或者Persist方法将前面的计算结果缓存&#xff0c;默认情况下会把数据以序列化的形式缓存在JVM的堆内存中。但是并不是这两个方法被调用时立即缓存&#xff0c;而是触发后面的action时&#xff0c;该RDD将会被缓存在计算节点的内存中&#xff0c;并供…...

【Linux】Linux系统安装Python3和pip3

1.说明 一般来说Linux会自带Python环境&#xff0c;可能是Python3或者Python2&#xff0c;可能有pip也可能没有pip&#xff0c;所以有时候需要自己安装指定的Python版本。Linux系统下的安装方式都大同小异&#xff0c;基本上都是下载安装包然后编译一下&#xff0c;再创建好软…...

用java进行base64加密

首先定义一组密钥,加密和解密使用同一组密钥private final String key "hahahahahaha";也可以随机生成密钥/*** 生成随机密钥* param keySize 密钥大小推荐128 256* return* throws NoSuchAlgorithmException*/public static String generateSecret(int keySize) th…...

torch函数合集

torch.tensor() 原型&#xff1a;torch.tensor(data, dtypeNone, deviceNone, requires_gradFalse) 功能&#xff1a;其中data可以是:list,tuple,NumPy,ndarray等其他类型,torch.tensor会从data中的数据部分做拷贝(而不是直接引用),根据原始数据类型生成相应类型的torch.Tenso…...

AcWing算法提高课-3.1.2信使

宣传一下算法提高课整理 <— CSDN个人主页&#xff1a;更好的阅读体验 <— 题目传送门点这里 题目描述 战争时期&#xff0c;前线有 nnn 个哨所&#xff0c;每个哨所可能会与其他若干个哨所之间有通信联系。 信使负责在哨所之间传递信息&#xff0c;当然&#xff0c;…...

Paddle OCR Win 11下的安装和简单使用教程

Paddle OCR Win 11下的安装和简单使用教程 对于中文的识别&#xff0c;可以考虑直接使用Paddle OCR&#xff0c;识别准确率和部署都相对比较方便。 环境搭建 目前PaddlePaddle 发布到v2.4&#xff0c;先下载paddlepaddle&#xff0c;再下载paddleocr。根据自己设备操作系统进…...

杂谈:数组index问题和对象key问题

面试题一&#xff1a; var arr [1, 2, 3, 4] 问&#xff1a;arr[1] ?; arr[1] ?答&#xff1a;arr[1] 2; arr[1] 2 这里可以再分为两个问题&#xff1a; 1、数组赋值 var arr [1, 2, 3, 4]arr[1] 10; // 数字场景 arr[10] 1; // 字符串场景 arr[a] 1; // 字符串…...

三天Golang快速入门—Slice切片

三天Golang快速入门—Slice切片Slice切片切片原理切片遍历append函数操作切片append添加append追加多个切片中删除元素切片合并string和slice的联系Slice切片 切片原理 由三个部分构成&#xff0c;指针、长度、容量指针&#xff1a;指向slice第一个元素对应的数组元素的地址长…...

腾讯会议演示者视图/演讲者视图

前言 使用腾讯会议共享PPT时&#xff0c;腾讯会议支持共享用户使用演示者视图/演讲者视图&#xff0c;而会议其他成员可以看到正常的放映视图。下面以Win10系统和Office为例&#xff0c;介绍使用步骤。值得一提的是&#xff0c;该方法同时适用于单显示屏和多显示屏。 腾讯会议…...

【C++】类与对象(一)

文章目录1、面向过程和面向对象初步认识2、类的引入3、类的定义4、类的访问限定符5、类的作用域6、类的实例化7、计算类对象的大小8、this指针9、 C语言和C实现Stack的对比1、面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题…...

JavaScript基本语法

本文提到的绝大多数语法都是与Java不同的语法,相同的就不会赘述了.JavaScript的三种引入方式内部js<body><script>alert(hello);</script> </body>行内js<body><div onclick"alert(hello)">这是一个div 点击一下试试</div>…...

OpenCV4.x图像处理实例-道路车辆检测(基于背景消减法)

通过背景消减进行道路车辆检测 文章目录 通过背景消减进行道路车辆检测1、车辆检测思路介绍2、BackgroundSubtractorMOG23、车辆检测实现在本文中,将介绍如何使用简单但有效的背景-前景减法方法执行车辆检测等任务。本文将使用 OpenCV 中使用背景-前景减法和轮廓检测,以及如何…...

pwnlab通关流程

pwnlab通关 关于文件包含&#xff0c;环境变量劫持的一个靶场 信息收集 靶机ip&#xff1a;192.168.112.133 开放端口 根据开放的端口信息决定从80web端口入手 目录信息 在images和upload路径存在目录遍历&#xff0c;config.php被渲染无法查看&#xff0c;upload.php需…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解

一、前言 在HarmonyOS 5的应用开发模型中&#xff0c;featureAbility是旧版FA模型&#xff08;Feature Ability&#xff09;的用法&#xff0c;Stage模型已采用全新的应用架构&#xff0c;推荐使用组件化的上下文获取方式&#xff0c;而非依赖featureAbility。 FA大概是API7之…...

GAN模式奔溃的探讨论文综述(一)

简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...