Java中ThreadLocal的深入理解
官方对ThreadLocal的描述:
"该类提供了线程局部(thread-local)变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其get或set方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal实例通常是类中的private static字段,它们希望将状态与某一个线程(例如,用户ID或事物ID)相关联。"
《Thinking in Java》中的描述:
防止任务在共享资源上产生冲突的第二种方式是根除对变量的共享。线程本地存储是一种自动化机制,可以为使用变量的每个不同的线程都创建不同的存储。因此,如果你有5个线程都要使用变量x所表示的对象,那线程本地存储就会生成5个用于x的不同的存储块。主要是,它们使得你可以将状态与线程关联起来。
三个要点:
1.每个线程都有自己的局部变量
每个线程都有一个独立于其它线程的上下文来保存这个变量,一个线程的本地变量对其它线程是不可见的。
2.独立于变量的初始化副本
ThreadLocal可以给一个初始值,而每个线程都会获得这个初始化值的一个副本,这样才能保证不同的线程都有一份拷贝。
3.状态与某一个线程相关联
ThreadLocal不是用于解决共享变量的问题的,不是为了协调线程同步而存在,而是为了方便每个线程处理自己的状态而引入的一个机制,就像《Thinking in Java》中描述的那样:”它们使得你可以将状态与线程关联起来。“理解这点对正确使用ThreadLocal至关重要。
源码举例:

从输出的结果可以看出,五个线程处理自己的本地变量值。

而这个测试的结果,并没有相同。这是因为实例为对象,所以初始值为一个对象的引用,那么五个线程的副本就是这个对象的引用的副本,也就是说这些引用还是指向同一个对象,所以就出现了这种情况。
ThreadLocal的接口方法:
- void set(T value):设置当前线程的线程局部变量的值;
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
//说明线程第一次使用线程本地变量(注意这里的第一次含义)
else
createMap(t, value);
}
- public T get():该方法返回当前线程所对应的线程局部变量;
public T get() {
//获取当前执行线程
Thread t = Thread.currentThread();
//取得当前线程的ThreadLocalMap实例
ThreadLocalMap map = getMap(t);
//如果map不为空,说明该线程已经有了一个ThreadLocalMap实例
if (map != null) {
//map中保存线程的所有的线程本地变量,我们要去查找当前线程本地变量
ThreadLocalMap.Entry e = map.getEntry(this);
//如果当前线程本地变量存在这个map中,则返回其对应的值
11 if (e != null)
return (T)e.value;
13 }
//如果map不存在或者map中不存在当前线程本地变量,返回初始值
return setInitialValue();
}
- public void remove():将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。当线程结束后,对应该线程的局部变量将被自动垃圾回收,所以显示调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度;
- protected T initialValue():返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的,这个方法是一个延迟调用方法,在线程第1次调用get()或set(T)时才执行,并且仅执行1次。ThreadLocal中的默认实现直接返回一个null。
这里注意,ThreadLocal中是有一个Map,但这个Map不是我们平时使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一个内部类,不对外使用的。当使用ThreadLocal存值时,首先是获取到当前线程对象,然后获取到当前线程本地变量Map,最后将当前使用的ThreadLocal和传入的值放到Map中,也就是说ThreadLocalMap中存的值是[ThreadLocal对象, 存放的值],这样做的好处是,每个线程都对应一个本地变量的Map,所以一个线程可以存在多个线程本地变量。下面提供一个简单的实现版本:

Java中ThreadLocal的深入理解的更多相关文章
- java中threadlocal的理解
[TOC] #java中threadlocal的理解##一.threadlocal的生命周期和ThreadLocalMap的生命周期可以吧TreadLocal看做是一个map来使用,只不过这个map是 ...
- Java中线程同步的理解 - 其实应该叫做Java线程排队
Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可 ...
- java中线程同步的理解(非常通俗易懂)
转载至:https://blog.csdn.net/u012179540/article/details/40685207 Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运 ...
- java中ThreadLocal的使用
文章目录 在Map中存储用户数据 在ThreadLocal中存储用户数据 java中ThreadLocal的使用 ThreadLocal主要用来为当前线程存储数据,这个数据只有当前线程可以访问. 在定 ...
- java中ThreadLocal类的使用
ThreadLocal是解决线程安全问题一个很好的思路,ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本,由于Key值不可重复, ...
- 微冷的雨之Java中的多线程初理解(一)
在讲解多线程前,我们必须理解什么是多线程?而且很多人都会将进程和线程做对比. 进程和线程 进程:进程是操作系统结构的基础,是一次程序的执行,是一个程序及其数据在处理机上顺序执行时所发生的活动,是程序在 ...
- 对Java中字符串的进一步理解
字符串在程序开发中无处不在,也是用户交互所涉及到最频繁的数据类型,那么字符串不仅仅就是我们简单的理解的String str = "abc";一起来更加深入的看一下 在Java中,字 ...
- Java中ThreadLocal的设计与使用
早在Java 1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新的选择.使用这个工具类可以很简洁地编写出优美的多线程程 ...
- Java学习疑惑(8)----可视化编程, 对Java中事件驱动模型的理解
我们编写程序就是为了方便用户使用, 我觉得UI设计的核心就是简洁, 操作过于繁琐的程序让很大一部分用户敬而远之. 即使功能强大, 但是人们更愿意使用易于操作的软件. 近年流行起来的操作手势和逐渐趋于成 ...
随机推荐
- 由枚举模块到ring0内存结构 (分析NtQueryVirtualMemory)
是由获得进程模块而引发的一系列的问题,首先,在ring3层下枚举进程模块有ToolHelp,Psapi,还可以通过在ntdll中获得ZwQuerySystemInformation的函数地址来枚举,其 ...
- MyEclipse — Maven+Spring+Struts+Hibernate 整合 [学习笔记-2]
引入Spring 修改 pox.xml 文件 添加jar包引用 <!-- spring3 --> <dependency> <groupId>org.springf ...
- Android 图片异步加载的体会,SoftReference已经不再适用
在网络上搜索Android图片异步加载的相关文章,目前大部分提到的解决方案,都是采用Map<String, SoftReference<Drawable>> 这样软引用的 ...
- 【Apache运维基础(2)】主配置文件说明
ServerTokens OS 系统信息,在访问出错时出现;把OS改为Minor,就不显示系统信息 ServerSignature On 把On改为Off就连普通的系统都给隐藏起来;改为Email就会 ...
- Spring笔记——配置Hibernate框架事务
原文:http://www.iteye.com/topic/1123347 Spring配置文件中关于事务配置总是由三个组成部分,DataSource.TransactionManager和代理机制这 ...
- iOS 消息转发
消息转发 delegate和protocol 类别 消息转发 当向someObject发送某消息,但runtime system在当前类和父类中都找不到对应方法的实现时,runt ...
- qt resize() 和 geometry()
resize(),设置的部件客户区的大小.只有当该部件被show后才生效,即geomery() 返回的才是 resize() 的客户区大小.
- HDU5092——Seam Carving(动态规划+回溯)(2014上海邀请赛重现)
Seam Carving DescriptionFish likes to take photo with his friends. Several days ago, he found that s ...
- jQuery-瀑布流-绝对定位布局(二)(延迟AJAX加载图片)
jQuery-瀑布流-绝对定位布局(二)(延迟AJAX加载图片) 瀑布流-绝对定位布局,与浮动布局的区别在于 1.布局不一样: 绝对定位:一个UL里面放置所有的绝对定位的LI: 浮动布局:多个(一 ...
- Android与OpenCV——重新下载安装和OpenCV匹配的Android开发环境
Android与OpenCV——重新下载安装和OpenCV匹配的Android开发环境 !!OpenCV4Android开发之旅(一)----OpenCV2.4简介及 app通过Java接口调用Ope ...