谈谈对ThreadLocal的理解?(基于jdk1.8)

在java的多线程模块中,ThreadLocal是经常被提问到的一个知识点,提问的方式有很多种,可能是循序渐进也可能是就像我的题目那样,因此只有理解透彻了,不管怎么问,都能游刃有余。

这篇文章主要从以下几个角度来分析理解

1、ThreadLocal是什么

2、ThreadLocal怎么用

3、ThreadLocal源码分析

4、ThreadLocal内存泄漏问题

下面我们带着这些问题,一点一点揭开ThreadLocal的面纱。若有不正之处请多多谅解,并欢迎批评指正。以下源码均基于jdk1.8。

一、ThreadLocal是什么

从名字我们就可以看到ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

从字面意思来看非常容易理解,但是从实际使用的角度来看,就没那么容易了,作为一个面试常问的点,使用场景那也是相当的丰富:

1、在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。

2、线程间数据隔离

3、进行事务操作,用于存储线程事务信息。

4、数据库连接,Session会话管理。

现在相信你已经对ThreadLocal有一个大致的认识了,下面我们看看如何用?

二、ThreadLocal怎么用

既然ThreadLocal的作用是每一个线程创建一个副本,我们使用一个例子来验证一下:
在这里插入图片描述

从结果我们可以看到,每一个线程都有各自的local值,我们设置了一个休眠时间,就是为了另外一个线程也能够及时的读取当前的local值。

这就是TheadLocal的基本使用,是不是非常的简单。那么为什么会在数据库连接的时候使用的比较多呢?

在这里插入图片描述

上面是一个数据库连接的管理类,我们使用数据库的时候首先就是建立数据库连接,然后用完了之后关闭就好了,这样做有一个很严重的问题,如果有1个客户端频繁的使用数据库,那么就需要建立多次链接和关闭,我们的服务器可能会吃不消,怎么办呢?如果有一万个客户端,那么服务器压力更大。

这时候最好ThreadLocal,因为ThreadLocal在每个线程中对连接会创建一个副本,且在线程内部任何地方都可以使用,线程之间互不影响,这样一来就不存在线程安全问题,也不会严重影响程序执行性能。是不是很好用。

以上主要是讲解了一个基本的案例,然后还分析了为什么在数据库连接的时候会使用ThreadLocal。下面我们从源码的角度来分析一下,ThreadLocal的工作原理。

三、ThreadLocal源码分析

在最开始的例子中,只给出了两个方法也就是get和set方法,其实还有几个需要我们注意。

在这里插入图片描述

方法这么多,我们主要来看set,然后就能认识到整体的ThreadLocal了:

1、set方法

在这里插入图片描述

从set方法我们可以看到,首先获取到了当前线程t,然后调用getMap获取ThreadLocalMap,如果map存在,则将当前线程对象t作为key,要存储的对象作为value存到map里面去。如果该Map不存在,则初始化一个。

OK,到这一步了,相信你会有几个疑惑了,ThreadLocalMap是什么,getMap方法又是如何实现的。带着这些问题,继续往下看。先来看ThreadLocalMap。

在这里插入图片描述

我们可以看到ThreadLocalMap其实就是ThreadLocal的一个静态内部类,里面定义了一个Entry来保存数据,而且还是继承的弱引用。在Entry内部使用ThreadLocal作为key,使用我们设置的value作为value。

还有一个getMap

ThreadLocalMap getMap(Thread t) {return t.threadLocals;}

调用当期线程t,返回当前线程t中的成员变量threadLocals。而threadLocals其实就是ThreadLocalMap。

2、get方法

在这里插入图片描述

通过上面ThreadLocal的介绍相信你对这个方法能够很好的理解了,首先获取当前线程,然后调用getMap方法获取一个ThreadLocalMap,如果map不为null,那就使用当前线程作为ThreadLocalMap的Entry的键,然后值就作为相应的的值,如果没有那就设置一个初始值。

如何设置一个初始值呢?

在这里插入图片描述

原理很简单

3、remove方法

在这里插入图片描述

从我们的map移除即可。

OK,其实内部源码很简单,现在我们总结一波

(1)每个Thread维护着一个ThreadLocalMap的引用

(2)ThreadLocalMap是ThreadLocal的内部类,用Entry来进行存储

(3)ThreadLocal创建的副本是存储在自己的threadLocals中的,也就是自己的ThreadLocalMap。

(4)ThreadLocalMap的键值为ThreadLocal对象,而且可以有多个threadLocal变量,因此保存在map中

(5)在进行get之前,必须先set,否则会报空指针异常,当然也可以初始化一个,但是必须重写initialValue()方法。

(6)ThreadLocal本身并不存储值,它只是作为一个key来让线程从ThreadLocalMap获取value。

OK,现在从源码的角度上不知道你能理解不,对于ThreadLocal来说关键就是内部的ThreadLocalMap。

四、ThreadLocal其他几个注意的点

只要是介绍ThreadLocal的文章都会帮大家认识一个点,那就是内存泄漏问题。我们先来看下面这张图。

在这里插入图片描述

上面这张图详细的揭示了ThreadLocal和Thread以及ThreadLocalMap三者的关系。

1、Thread中有一个map,就是ThreadLocalMap

2、ThreadLocalMap的key是ThreadLocal,值是我们自己设定的。

3、ThreadLocal是一个弱引用,当为null时,会被当成垃圾回收

4、重点来了,突然我们ThreadLocal是null了,也就是要被垃圾回收器回收了,但是此时我们的ThreadLocalMap生命周期和Thread的一样,它不会回收,这时候就出现了一个现象。那就是ThreadLocalMap的key没了,但是value还在,这就造成了内存泄漏。

解决办法:使用完ThreadLocal后,执行remove操作,避免出现内存溢出情况。

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

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

相关文章

江苏学考计算机,学长建议 江苏考生 位次在4000-10000 想报考计算机的同学

本人对高考志愿填报有点执念,毕竟是第一次真正重大的抉择,以后每年都会看看高校录取情况,加上今年刚找工作,对互联网企业的选人标准比较了解,所以斗胆来提提建议。核心观点,多看看985的分校区,比…

mybatis if test判断 list不为空

<if test"list!null and list.size()!0"></if>注意 如果使用list.isNotEmpty()会报错&#xff0c;提示不是一个方法

数字时钟html5 js,html5 canvas js(数字时钟)实例代码

canvas dClock您的浏览器太古董了&#xff0c;升级吧&#xff01;var clock document.getElementById("clock");var cxt clock.getContext("2d");//显示数字时钟function showTime(m, n) {cxt.clearRect(0, 0, 500, 500);var now new Date;var hour no…

简单理解BigDecimal.valueof(Double t)与BigDecimal.valueof(String t)的区别——BigDecimal

上面的代码主要的区别在于 初始化BigDecimal时形参是double、String和float的区别 从上面可以看到&#xff0c;当double 和 float 时&#xff0c;实际保存的值并不是是准确的0.99&#xff0c;这是为什么呢 大致的原因是&#xff1a; BigDecimal(double val)将会把double型二…

在线计算机标准版,NCRE全国计算机等级一标准版级考试复习资料.doc

全国计算机等级一级考试复习资料内容&#xff1a;计算机基础知识、文字处理软件WORD复习题类型&#xff1a;填空题、选择题、综合题复习题数量&#xff1a;复习时间&#xff1a;12月5日—12月9日考试时间&#xff1a;12月9日(周三下午第三节课)参考对象&#xff1a;电子高专的学…

mysql 统计当天,本周,本月,上一月的数据

今天 select * from ht_invoice_information where year(create_date)year(date_sub(now(),interval 1 year)); select * from 表名 where to_days(时间字段名) to_days(now());昨天 select * from 表名 where to_days( now( ) ) - to_days( 时间字段名) < 1近期7天 sel…

下图中的蓝月亮为科学家用计算机,2018年高一地理前半期课时练习试卷带答案和解析...

目前人类可以观察到的最高级别天体系统是A. 总星系 B. 银河系 C. 太阳系 D. 地月系【答案】A【解析】本题考查天体系统的层次。距离相近的天体因相互吸引和相互绕转&#xff0c;构成不同级别的天体系统&#xff0c;天体系统的层次为&#xff1a;最高一级为总星系(即目前所知的宇…

邮政计算机网络,邮政计算机网络论文(共2018字).doc

邮政计算机网络论文(共2018字)邮政计算机网络论文(共2018字)一、邮政计算机网络基本现状分析邮政网络系统资源不足&#xff0c;数据传输技术滞后随着邮政储蓄代收付业务和电子邮政业务的快速发展&#xff0c;市场需要变化加快&#xff0c;现有网络系统资源不足&#xff0c;设备…

HashMap的put方法返回值问题

API文档中的描述&#xff1a; 先看一个例子 Map<Character, Integer> map new HashMap<Character, Integer>(); System.out.println(map.put(a, 0)); // null System.out.println(map.put(a, 1)); // 0 System.out.println(map.put(a, 2)); // 1 System.out.pri…

资金时间价值的计算机应用视频讲解,第八章资金时间价值与方案经济比选20161018讲解.ppt...

第八章资金时间价值与方案经济比选20161018讲解(二)净年值(NAV) 1、含义 净年值也称净年金(记作NAV)&#xff0c;它是把项目寿命期内的净现金流量按设定的折现率折算成与其等值的各年年末的等额净现金流量值。 2&#xff0e;计算 先求该项目的净现值&#xff0c;然后乘以资金回…

[Microsoft][ODBC SQL Server Driver][SQL Server]对象名 ‘***‘无效问题的解决方案器

[Microsoft][ODBC SQL Server Driver][SQL Server]对象名 ***无效问题的解决方案 在用Java进行SQL server数据编程时出现数据库连接成功后对表进行操作时报错“表名无效”。在网上搜了相关问题后均未解决&#xff0c;最后通过在表名前加数据库名的方式得以解决&#xff0c;记录…

Java中将Map转换为JSON

一个注意的地方&#xff1a;要选对jar包 Map map new HashMap();map.put("success", "true");map.put("photoList", photoList);map.put("currentUser", "zhang");//net.sf.json.JSONObject 将Map转换为JSON方法JSONObject…

掌上通计算机一级考试在线安装,计算机一级掌上通

计算机一级掌上通app是一款计算机等级考试学习的软件&#xff0c;让你在线学习计算机的操作知识&#xff0c;便于通过等级考试&#xff0c;快速准确&#xff1b;软件提供海量选择题的题库&#xff0c;随时随地做题&#xff0c;简单又方便&#xff0c;还有计算机基本操作讲解&am…

java获取时间,本周,本月,本季度的起始

package com.yong.util; import java.util.Calendar; import java.util.Date;public class TestDate {public static void main(String[] args) {System.out.println("当前时间&#xff1a;" new Date().toLocaleString());System.out.println("当天0点时间&…

东莞理工学院计算机ccf,中国计算机学会东莞分部成立

为更全面和更好地服务东莞计算机领域专业人士的学术和职业发展&#xff0c;在中国计算机学会(CCF)总部和广州、深圳分部的指导和协助下&#xff0c;由东莞理工学院和中美融易孵化器牵头&#xff0c;联合东莞市各大高校、学会、企业&#xff0c;共同发起成立中国计算机学会东莞分…

mybatis获取表名——mybatis动态调用表名和字段名#{},${}

一直在使用Mybatis这个ORM框架&#xff0c;都是使用mybatis里的一些常用功能。今天在项目开发中有个业务是需要限制各个用户对某些表里的字段查询以及某些字段是否显示&#xff0c;如某张表的某些字段不让用户查询到。这种情况下&#xff0c;就需要构建sql来动态传入表名、字段…

浙大计算机学院辅导员,浙大博士应聘辅导员被指丢脸 月薪仅1000元

浙江在线05月02日讯 浙江大学动物营养与饲料科学专业博士生冯一秦这两天正在准备博士论文答辩&#xff0c;他已经找好了工作单位——在工商大学当大学生辅导员&#xff0c;一度成为浙大BBS头条新闻——高职低聘&#xff0c;很丢脸吗&#xff1f;网友跟帖&#xff1a;这样的博士…

html5 中 video 标签,H5页面中 video 标签的坑

兼容性差因为是原生组件层级最高iOS系统 和 安卓系统展示方式不一样整理了一些有效的方法关于 标签的 css 样式//全屏按钮video::-webkit-media-controls-fullscreen-button {display: none;}//播放按钮video::-webkit-media-controls-play-button {display: none;}//进度条vid…

男孩读计算机好还是铁路学校好,中专学计算机好还是铁路好?

随着石家庄通用交通学校春季招生火热进行中&#xff0c;有很多同学会在微信上咨询武老师一些学校的问题&#xff0c;比如说选什么专业好&#xff0c;将来哪个专业比较好找工作等等&#xff0c;最近在咨询中&#xff0c;有个同学想学铁路专业也想学计算机专业&#xff0c;就很纠…

谈谈对 Spring 的理解

认识 Spring 框架 Spring 框架是 Java 应用最广的框架&#xff0c;它的成功来源于理念&#xff0c;而不是技术本身&#xff0c;它的理念包括 IoC (Inversion of Control&#xff0c;控制反转) 和 AOP(Aspect Oriented Programming&#xff0c;面向切面编程)。 什么是 Spring&…