【JUC】15-ThreadLocal线程局部变量

1. ThreadLocal

 ThreadLocal提供线程局部变量。每个线程在访问ThreadLocal实例的时候都有自己的、独立的变量副本。ThreadLocal实例通常是类中的私有静态字段,使用它的目的是希望将状态(用户ID或事务ID)与线程关联起来。

class Saler {ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(()->0);public void add(int x) {threadLocal.set(x+ threadLocal.get());}public int getInt() {return threadLocal.get();}public void remove() {threadLocal.remove();}
}
public class demo01 {public static void main(String[] args) {Saler saler = new Saler();try {for(int i=0; i<5; i++) {int nextInt = new Random().nextInt(100);saler.add(nextInt);System.out.println(saler.getInt());}} finally {saler.remove();}}
}

 ThreadLocal要及时清除。

class User {ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(()->0);public void set() {threadLocal.set(threadLocal.get()+10);}public int get() {return threadLocal.get();}public void remove() {threadLocal.remove();}
}public class demo02 {public static void main(String[] args) {User user = new User();ExecutorService threadPool = Executors.newFixedThreadPool(3);try {for(int i=0; i<10; i++) {threadPool.submit(()->{try {user. set();System.out.println(user.get());} catch (Exception e) {throw new RuntimeException(e);} finally {user.remove();}});}} catch (Exception e) {throw new RuntimeException(e);} finally {threadPool.shutdown();}}
}

2. ThreadLocalMap

  ThreadLocalMap是一个以ThreadLocal为key,任意对象为value的Entry对象。
在这里插入图片描述

3. ThreadLocal弱引用

3.1 内存泄漏

 不再会被使用的对象或者变量占用的内存不能被回收,就是内存泄漏。

        static class Entry extends WeakReference<ThreadLocal<?>> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}

3.2 Reference

 finalize()方法可以在垃圾收集器将对象从内存中清除出去之前做出必要的清理方法。
在这里插入图片描述
强引用:出现OOM也不会对该对象进行回收。即使该对象以后不用到也不会被回收。容易导致内存泄漏。

class MyObj {@Overrideprotected void finalize() throws Throwable {System.out.println("MyObj is removed...");}
}public class demo03 {public static void main(String[] args) {MyObj myObj = new MyObj();myObj = null;// 人工开启gcSystem.gc();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("Completed");}
}

软引用:当系统内存充足时,不会被回收。系统内存不足会被回收。应用大量读取图片,可以用Map存储图片地址和SoftReference的Bitmap。

class MyObj {@Overrideprotected void finalize() throws Throwable {System.out.println("MyObj is removed...");}
}public class demo03 {public static void main(String[] args) {SoftReference<MyObj> myObj = new SoftReference<>(new MyObj());System.gc();System.out.println(myObj);try {byte[] bytes = new byte[20 * 1024 * 1024];System.out.println(myObj);} catch (Exception e) {} finally {System.out.println("completed");}}
}

弱引用:只要进行gc就会被回收。软引用

class MyObj {@Overrideprotected void finalize() throws Throwable {System.out.println("MyObj is removed...");}
}public class demo03 {public static void main(String[] args) {WeakReference<MyObj> weakReference = new WeakReference<>(new MyObj());System.out.println(weakReference);System.gc();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(weakReference);}
}

虚引用:用于监控通知使用,无法访问相应的对象。虚引用对象被回收会被放在ReferenceQueue中。

class MyObj {@Overrideprotected void finalize() throws Throwable {System.out.println("MyObj is removed...");}
}public class demo03 {public static void main(String[] args) {MyObj myObj = new MyObj();ReferenceQueue referenceQueue = new ReferenceQueue<>();PhantomReference phantomReference = new PhantomReference<>(myObj, referenceQueue);List<byte[]> list = new ArrayList<>();new Thread(()->{while (true) {list.add(new byte[1 * 1024 * 1024]);System.out.println(phantomReference.get() + " add ok");}}).start();new Thread(()->{while(true) {Reference poll = referenceQueue.poll();if (poll!=null) {System.out.println(poll + "有需对象加入队列");break;}}}).start();}
}

4. ThreadLocal弱引用

 ThreadLocal本身作为一个key来让线程从ThreadLocalMap中获取value。从而实现线程之间的数据隔离。
在这里插入图片描述
在这里插入图片描述
为什么Entry要使用弱引用?
当func1执行完毕后,栈帧销毁强引用tl没有了。使用弱引用就大概率会减少内存泄漏风险(key为null需单独处理),可以让ThreadLocal对象在执行完毕后顺利被回收且key引用指向null。
 虽然弱引用,保证key指向的ThreadLocal对象能被及时回收,但是v指向的value对象是需要ThreadLocalMap调用get、set时发现key为null时,才会去回收整个entry、value,因此弱引用不能100%保证内存不泄露。需要手动调用remove方法来删除ThreadLock对象。底层通过调用expungeStaleEntry( ) 实现清除废旧的entry。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/422124.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MATLAB实现Dijkstra算法和Floyd算法

目录 1、文件功能介绍 2、代码执行效果展示 3、Dijkstra算法求图的单源最短路径 4、Dijkstra fullPath的更新逻辑 5、DIjkstra算法流程图 6、Floyd算法实现图的任意两点间最短路径 7、Floyd算法流程图 8、Floyd fullPath的更新逻辑&#xff08;非递归算法&#xff09; …

labview串口大数据量报错的一种解决思路(通过tcp进行写入和读取串口数据)

因为项目要求&#xff0c;用labview给客户开发了一个上位机&#xff0c;在现场给客户调试上位机时&#xff0c;发现了几种奇怪的现象 1&#xff1a;客户样件有两路串口&#xff0c;一路串口可以多字节进行发送数据&#xff0c;一路只能单字节发送数据&#xff0c;每次单字节数据…

Pygame中获取鼠标按键状态的方法

在《Pygame中获取鼠标位置的方法》中提到&#xff0c;可以通过鼠标事件和mouse模块中的函数获取鼠标位置&#xff0c;这两种方法同样适用于获取鼠标按键状态。 1 通过鼠标点击事件获取鼠标按键状态 通过鼠标点击事件获取鼠标按键状态的代码如图1所示。 图1 鼠标点击事件获取鼠…

Gin-封装自动路由

O.0 思路一、API二、控制层三、自动路由核心四、分组路由外加中间件使用 思路 由于Java转Go直接使用的goframe框架&#xff0c;然学习Gin时觉得一个接口一个路由太麻烦&#xff0c;于是有了...1、在请求结构体中采用标签的形式&#xff0c;直接给出路由和请求方式 2、在控制层…

QXml 使用方法

VS2019 QT 编译工具链问题解决 使用winqtdeploy.exe 打包环境就可以正常运行&#xff0c;缺少某一个运行库引起的 简易使用python脚本编译运行 Python3 中的 slots 和 QT 中的 slots 宏定义重复, 放在不同的文件中进行调用可以避免 还是比较习惯从源码包引入&#xff08;方便定…

【区块链通用服务平台及组件】信息数据流转验真技术研究项目 | FISCO BCOS应用案例

在日常工作中&#xff0c;相关系统每天会产生大量数据&#xff0c;系统之间有多种模式数据交互方式&#xff0c;数据监管工作量巨大&#xff0c;急需 数据追溯定位工具来辅助监管&#xff1b;数据在生产过程中经常会出现采集、提交、修改、删除等操作&#xff0c;需要对数据变更…

Vue(9)——.sync修饰符、ref和$refs、$nextTick

.sync 作用:可以实现子组件与父组件数据的双向绑定&#xff0c;简化代码。 特点&#xff1a;prop属性名&#xff0c;可以自定义&#xff0c;非固定位value 场景&#xff1a;封装弹框类的基础组件&#xff0c;visible属性 true显示&#xff0c;false隐藏 本质&#xff1a;就是 …

鸿蒙界面开发——组件(7):组件导航 页面路由

组件导航 (Navigation)(推荐) Navigation() Navigation(pathInfos: NavPathStack)Navigation是路由容器组件&#xff0c;一般作为首页的根容器&#xff0c;包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。Navigation组件适用于模块内和跨模块的路由切换&#xff0c…

2024年金九银十最新版Java面试题及答案整理(持续更新)

2024年金九银十到了&#xff0c;发现网上很多Java面试题都没有答案&#xff0c;所以花了很长时间搜集整理出来了这套Java面试题大全~这套互联网 Java 工程师面试题包括了&#xff1a;MyBatis、ZK、Dubbo、EL、Redis、MySQL、并发编程、Java面试、Spring、微服务、Linux、Spring…

文件加密最简单的方法有哪些?十个电脑文件加密方法【超详细】

在当今数字化和信息化的时代&#xff0c;数据已成为企业最重要的资产之一。内部数据外泄不仅可能导致商业秘密的丧失&#xff0c;还可能对企业的声誉和财务健康造成严重影响。为了有效防止内部数据外泄&#xff0c;企业需要实施综合的防泄密解决方案。以下是十大最佳防泄密解决…

内网安全-横向移动【3】

1.域横向移动-内网服务-Exchange探针 Exchange是一个电子右键服务组件&#xff0c;由微软公司开发。它不仅是一个邮件系统&#xff0c;还是一个消息与协作系统。Exchange可以用来构建企业、学校的邮件系统&#xff0c;同时也是一个协作平台&#xff0c;可以基于此开发工作流、…

19:I2C一:程序模拟I2C通信时序

I2C 1、什么是I2C2、I2C的通信时序2.1&#xff1a;起始信号2.2&#xff1a;停止信号2.3&#xff1a;主机向从机发送一个字节数据2.4&#xff1a;主机向从机读取一个字节数据2.5&#xff1a;主机接收应答2.6&#xff1a;主机发送应答 3、程序模拟I2C的通信时序3.1&#xff1a;指…

NX1872三维电气布线

电气部件审核与定义

Windows系统介绍

文章目录 1、Windows启动过程1.1 启动过程BIOS1.2 启动过程MBR1.3 启动过程 GPT1.4 启动过程BootMgr1.5 启动过程Winload.exe1.6 启动过程1.7 explorer.exe 2、Windows重要进程及组件2.1 注册表Services注册表服务管理器Services.mscsc.exe计划任务taskschd.msc计划任务schtask…

区块链学习笔记1--比特币

区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。 从狭义上来说&#xff1a;区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一种链式数据结构&#xff0c;并以密码学的方式保证的不可篡改和不可伪造的分布式账本。 意思就是…

第67期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

组播 2024 9 11

PIM&#xff08;Protocol Independent Multicast&#xff09;是一种常用的组播路由协议&#xff0c;其独立于底层的单播路由协议&#xff0c;能够在多种网络环境中有效地实现多播路由功能。PIM主要有两种模式&#xff1a;PIM Sparse Mode (PIM-SM) 和 PIM Dense Mode (PIM-DM)&…

DDoS对策是什么?详细解说DDoS攻击难以防御的理由和对策方法

攻击规模逐年增加的DDoS攻击。据相关调查介绍&#xff0c;2023年最大的攻击甚至达到了700Gbps。 为了抑制DDoS攻击的危害&#xff0c;采取适当的对策是很重要的。 特别是在网站显示花费时间或频繁出现504错误的情况下&#xff0c;可能已经受到了DDoS攻击&#xff0c;需要尽早采…

Spring面试

一、对Spring的理解 &#xff08;一&#xff09;Spring的发展史 &#xff08;二&#xff09;Spring的体系结构 &#xff08;三&#xff09;Spring相关组件 1.Spring和SpringMVC的关系 2.Spring和SpringBoot的关系 3.Spring和SpringCloud的关系 4.Spring和SpringSecurity的…

C语言基础——⑩③数据结构——②栈和队列

一、栈(Stack) 1、基本概念 栈是一种逻辑结构&#xff0c;是特殊的线性表。特殊在&#xff1a; 只能在固定的一端操作 只要满足上述条件&#xff0c;那么这种特殊的线性表就会呈现一种“后进先出”的逻辑&#xff0c;这种逻辑就被称为栈。栈 在生活中到处可见&#xff0c;比…