java 线程变量put_Java线程(篇外篇):线程本地变量ThreadLocal

首先说明ThreadLocal存放的值是线程内共享的,线程间互斥的,主要用于线程内共享一些数据,避免通过参数来传递,这样处理后,能够优雅的解决一些实际问题,比如hibernate中的OpenSessionInView,就是使用ThreadLocal保存Session对象,还有我们经常用ThreadLocal存放Connection,代码如:

/**

* 数据库连接管理类

* @author 爽

*

*/

public class ConnectionManager {

/** 线程内共享Connection,ThreadLocal通常是全局的,支持泛型 */

private static ThreadLocal threadLocal = new ThreadLocal();

public static Connection getCurrConnection() {

// 获取当前线程内共享的Connection

Connection conn = threadLocal.get();

try {

// 判断连接是否可用

if(conn == null || conn.isClosed()) {

// 创建新的Connection赋值给conn(略)

// 保存Connection

threadLocal.set(conn);

}

} catch (SQLException e) {

// 异常处理

}

return conn;

}

/**

* 关闭当前数据库连接

*/

public static void close() {

// 获取当前线程内共享的Connection

Connection conn = threadLocal.get();

try {

// 判断是否已经关闭

if(conn != null && !conn.isClosed()) {

// 关闭资源

conn.close();

// 移除Connection

threadLocal.remove();

conn = null;

}

} catch (SQLException e) {

// 异常处理

}

}

}

这样处理的好处:

统一管理Connection;

不需要显示传参Connection,代码更优雅;

降低耦合性。

ThreadLocal有四个方法,分别为:

initialValue

protected T initialValue()

返回此线程局部变量的当前线程的初始值。最多在每次访问线程来获得每个线程局部变量时调用此方法一次,即线程第一次使用 get() 方法访问变量的时候。如果线程先于 get 方法调用 set(T) 方法,则不会在线程中再调用 initialValue 方法。

该实现只返回 null;如果程序员希望将线程局部变量初始化为 null 以外的某个值,则必须为 ThreadLocal 创建子类,并重写此方法。通常,将使用匿名内部类。initialValue 的典型实现将调用一个适当的构造方法,并返回新构造的对象。返回:返回此线程局部变量的初始值

get

public T get()

返回此线程局部变量的当前线程副本中的值。如果这是线程第一次调用该方法,则创建并初始化此副本。返回:此线程局部变量的当前线程的值

set

public void set(T value)

将此线程局部变量的当前线程副本中的值设置为指定值。许多应用程序不需要这项功能,它们只依赖于 initialValue() 方法来设置线程局部变量的值。参数:value - 存储在此线程局部变量的当前线程副本中的值。

remove

public void remove()

移除此线程局部变量的值。这可能有助于减少线程局部变量的存储需求。如果再次访问此线程局部变量,那么在默认情况下它将拥有其 initialValue。

很多人对ThreadLocal存在一定的误解,说ThreadLocal中有一个全局的Map,set时执行map.put(Thread.currentThread(), value),get和remove时也同理,但SUN的大师们是否是如此实现的,我们只能去看源码了。

set方法:

/**

* Sets the current thread's copy of this thread-local variable

* to the specified value.  Most subclasses will have no need to

* override this method, relying solely on the {@link #initialValue}

* method to set the values of thread-locals.

*

* @param value the value to be stored in the current thread's copy of

*        this thread-local.

*/

public void set(T value) {

// 获取当前线程对象

Thread t = Thread.currentThread();

// 获取当前线程本地变量Map

ThreadLocalMap map = getMap(t);

// map不为空

if (map != null)

// 存值

map.set(this, value);

else

// 创建一个当前线程本地变量Map

createMap(t, value);

}

/**

* Get the map associated with a ThreadLocal. Overridden in

* InheritableThreadLocal.

*

* @param  t the current thread

* @return the map

*/

ThreadLocalMap getMap(Thread t) {

// 获取当前线程的本地变量Map

return t.threadLocals;

}

这里注意,ThreadLocal中是有一个Map,但这个Map不是我们平时使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一个内部类,不对外使用的。当使用ThreadLocal存值时,首先是获取到当前线程对象,然后获取到当前线程本地变量Map,最后将当前使用的ThreadLocal和传入的值放到Map中,也就是说ThreadLocalMap中存的值是[ThreadLocal对象, 存放的值],这样做的好处是,每个线程都对应一个本地变量的Map,所以一个线程可以存在多个线程本地变量。

get方法:

/**

* Returns the value in the current thread's copy of this

* thread-local variable.  If the variable has no value for the

* current thread, it is first initialized to the value returned

* by an invocation of the {@link #initialValue} method.

*

* @return the current thread's value of this thread-local

*/

public T get() {

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

if (map != null) {

ThreadLocalMap.Entry e = map.getEntry(this);

if (e != null)

return (T)e.value;

}

// 如果值为空,则返回初始值

return setInitialValue();

}       有了之前set方法的分析,get方法也同理,需要说明的是,如果没有进行过set操作,那从ThreadLocalMap中拿到的值就是null,这时get方法会返回初始值,也就是调用initialValue()方法,ThreadLocal中这个方法默认返回null。当我们有需要第一次get时就能得到一个值时,可以继承ThreadLocal,并且覆盖initialValue()方法。

(完)

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

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

相关文章

深度解读:人体防御病毒的免疫力究竟是什么?

来源:国际仿生工程学会“免疫力作为机体免除瘟疫的一种能力,已被广大民众广泛使用,特别是本次新型冠状病毒的暴发,更是使得免疫力在新闻媒体中广泛传播。对于这样一个极其抽象模糊的术语,我们需要理解其真实的含义是什…

洛谷 1087——FBI树

题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串。 FBI树是一种二叉树,它的结点类型也包括F结点,B结点和I结点三种。由一个长度为2^N的“…

python开发web使用什么工具_常用的Python web开发工具盘点

www.oldboyedu.com老男孩IT教育,只培养技术精英常用的Python web开发工具盘点Python是一门动态、面向对象语言。其最初就是作为一门面向对象语言设计的,并且在后期又加入了一些更高级的特性。除了语言本身的设计目的之外,Python标准库也是值得…

java的add方法的使用_Java HashSet add()方法与示例

HashSet类add()方法add()方法在java.util包中可用。当尚不存在给定元素时,使用add()方法将其插入此HashSet中,否则它将忽略它并返回false。add()方法是一种非静态方法,只能通过类对象访问,如果尝试使用类名称访问该方法&#xff0…

国自然:信息科学部优先发展领域及主要研究方向(含跨科学部)

来源:科奖多媒体中心“十三五”期间,通过支持我国优势学科和交叉学科的重要前沿方向,以及从国家重大需求中凝练可望取得重大原始创新的研究方向,进一步提升我国主要学科的国际地位,提高科学技术满足国家重大需求的能力…

缓冲区不能为空。 参数名: buffer_Java Nio 之Buffer

了解历史在 java1.4之前java io ,最核心的点是在"流"上;java io 的两大基石InputStream和OutputStream 也就是大家耳熟能祥的输入流和输出流,通过这个两个基石可以实现从外界读取数据到内存,以及将内存中数据写到外界;但是输入流和…

怎样把java项目转换成web项目_Eclipse中将Java项目转换成Web项目的方法

注意:0.点击Further configuration available,修改eclipse默认的WebContent 并修改为WebRoot,勾选Generate web.xml deployment descriptor1.需要把web 工程的版本改成2.5本地项目:struts2-3其中的无需修改的文件:org.…

新增方法

//新增方法addRecord : function() {var me this;var height 500; //取得当前屏幕高度var width 500; //取得当前屏幕宽度var content Ext.create("BeidaSoft.SFJCGL.rcjwgl.bdgl.BdglAddPanel", {}); var win new Ext.Window({layout:fit,width:wi…

机器人行业疫情之下的“危”与“机”

来源:腾讯网口罩脱销令口罩生产线炙手可热,医护人士紧缺令送药机器人走俏,站场监控让自动测体温机器人成为网红,武汉街头配送出现物流机器人身影……新型冠状病毒感染肺炎疫情,给机器人和智能制造行业带来了意想不到的…

线性查找python_Python实现搜索算法的实例代码

将数据存储在不同的数据结构中时,搜索是非常基本的必需条件。最简单的方法是遍历数据结构中的每个元素,并将其与您正在搜索的值进行匹配。这就是所谓的线性搜索。它效率低下,很少使用,但为它创建一个程序给出了我们如何实现一些高…

mysql 二进制日志变化_MySQL运维之二进制日志

MySQL二进制日志里保存会造成或可能造成数据变化的SQL语句。通过二进制日志可以完成如实时异地容灾备份、读写分离、数据恢复等功能。下面,我们一起来看看Mysql二进制日志。开启bin-log日志Mysql默认是没有开启bin-log日志的,需要我们自己去添加配置。lo…

Python 模块(二)

1 logging 模块 logging有两种的配置的方式,configure、logger 1.1 config方式 import logging日志的配置:config模式 只能选择在屏幕或者在文件输出logging.basicConfig(levellogging.DEBUG,format%(asctime)s [%(lineno)s] %(message)s ,filenamelog.t…

影响和改变世界的50件发明专利,猜下中国有几个?

来源:国家知识产权局创新创造未来,专利改变世界。最近几十年究竟有哪些专利真正改变了世界呢?国家识产权局选取了一批具有历史意义的、促进社会经济发展的、对人类社会产生重要影响的中外专利。未来智能实验室的主要工作包括:建立…

js 自动分配金额_JS内存图以及原型与原型链

内存以及内存图在JS中,每一个数据都需要一个内存空间。内存空间又被分为两种,栈内存(stock)与堆内存(heap)。JS内存空间分为栈(stack)、堆(heap)、池(一般也会归类为栈中)。 其中栈存放变量,堆存放复杂对象,池存放常量。JS中的基础…

全球首个AI宇宙模拟器不仅有6亿光年宽度,还“自行”跑出了暗物质

来源:大数据文摘《创世纪》里,神用7天创造了这个世界。而现在,你可能也有机会体验这个过程,创造一个属于自己的宇宙。Space Engine 0.990版本在Steam平台发售不到一天,近300测评全部为最高评价。之后,还得到…

一个HelloWorld网站

一个HelloWorld网站 点击直达 介绍 很多技术在里面都有很多的HelloWorld 当初是我在windows下使用redis在官方文档没有找到入门的资料发现的 个人理解 作为HelloWorld是不错的,当然还有一些东西值得看,参考用过直接上某个技术的官方文档。 转载于:https://www.cnblogs.com/bean…

js 延迟几秒执行_深入研究 Node.js 的回调队列

// 每日前端夜话 第365篇// 正文共:3000 字// 预计阅读时间:10 分钟队列是 Node.js 中用于有效处理异步操作的一项重要技术。在本文中,我们将深入研究 Node.js 中的队列:它们是什么,它们如何工作(通过事件循环)以及它们…

java官方 jax rs_jboss7 Java API for RESTful Web Services (JAX-RS) 官方文档

原文:https://docs.jboss.org/author/display/AS7/JavaAPIforRESTfulWebServices(JAX-RS)ContentTutorial OverviewThis chapter describes the Java API for RESTful web services (JAX-RS, defined in JSR331). RESTEasy is an portable implementation of this s…

数据结构-王道2017-第5章 图

1.图的基本概念 1)图的定义 图G由顶点集V和边集E组成,记为G(V,E),其中V(G)表示图G中定点的有限非空集;E(G)表示图G中顶点之间的关系(边)集合。V{v1,v2,..,vn},用|V|表示图G中顶点的个数,也称为图G的阶&…

python两个参数or循环_python学习笔记(四)、条件、循环及其他语句

1 再谈print和import1.1 打印多个参数print 能够同时打印多个表达式,并且能自定义分隔符。如下:print(a,b,c)  ——> a b cprint(a,b,c,sep"_")  ——> a_b_c1.2 import导入模块时,能够给导入的模块取一个别名(相对于生活…