java ThreadLocal使用
1、源码分析
此处以JDK1.8版本分析
1.1 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();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
此处的ThreadLocalMap为ThreadLocal的一个内部类,用Entry来存储要设置的值。如下
static class ThreadLocalMap {
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
}
看下getMap()方法,用于返回当前ThreadLocal维护的ThreadLocalMap对象,如下
/**
* Get the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param t the current thread
* @return the map
*/
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
此处的t.threadLocals为当前Thread维护的ThreadLocalMap对象
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
再看下createMap()方法,用于为当前Thread没有ThreadLocalMap时新建一个ThreadLocalMap,如下
/**
* Create the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param t the current thread
* @param firstValue value for the initial entry of the map
*/
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
从源码中可以看出set方法过程:获取当前线程,并作为句柄去获取ThreadLocalMap,如果ThreadLocalMap存在,则以当前ThreadLocal对象为key,传入的对象为value进行存储。否则新建一个和当前线程相关联的ThreadLocalMap来存储。
1.2 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) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
从源码可以看出也是以当前线程为句柄获取ThreadLocalMap对象,如果存在则返回当前线程的ThreadLocal为key对应的值,否则设置初始值setInitialValue
/**
* Variant of set() to establish initialValue. Used instead
* of set() in case user has overridden the set() method.
*
* @return the initial value
*/
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
其中initialValue返回null
/**
* Returns the current thread's "initial value" for this
* thread-local variable. This method will be invoked the first
* time a thread accesses the variable with the {@link #get}
* method, unless the thread previously invoked the {@link #set}
* method, in which case the {@code initialValue} method will not
* be invoked for the thread. Normally, this method is invoked at
* most once per thread, but it may be invoked again in case of
* subsequent invocations of {@link #remove} followed by {@link #get}.
*
* <p>This implementation simply returns {@code null}; if the
* programmer desires thread-local variables to have an initial
* value other than {@code null}, {@code ThreadLocal} must be
* subclassed, and this method overridden. Typically, an
* anonymous inner class will be used.
*
* @return the initial value for this thread-local
*/
protected T initialValue() {
return null;
}
1.3 remove()方法
/**
* Removes the current thread's value for this thread-local
* variable. If this thread-local variable is subsequently
* {@linkplain #get read} by the current thread, its value will be
* reinitialized by invoking its {@link #initialValue} method,
* unless its value is {@linkplain #set set} by the current thread
* in the interim. This may result in multiple invocations of the
* {@code initialValue} method in the current thread.
*
* @since 1.5
*/
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
从源码可以很容易看出remove的作用过程,不做详细分析。为了避免内存泄漏问题,尽量在当前线程处理完之后手动进行remove操作。
2、总结
从上面的源码可以看出ThreadLocal设置的值和线程相关,可以理解为是线程的私有的访问区域,其他线程无法访问,实现了“数据隔离”效果。和解决并发问题和共享变量无关
每个Thread都维护者一个ThreadLocalMap的引用。
java ThreadLocal使用的更多相关文章
- Java ThreadLocal的使用
Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量.因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的Thread ...
- Java ThreadLocal 源代码分析
Java ThreadLocal 之前在写SSM项目的时候使用过一个叫PageHelper的插件 可以自动完成分页而不用手动写SQL limit 用起来大概是这样的 最开始的时候觉得很困惑,因为直接使 ...
- java threadLocal的初探
在网上找了半天,终于找到一篇靠谱的文章了. 文章地址:http://qifuguang.me/2015/09/02/[Java%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6% ...
- Java ThreadLocal Example(java中的ThreadLocal例子)
Java ThreadLocal is used to create thread local variables. We know that all threads of an Object sha ...
- Java ThreadLocal
ThreadLocal类,代表一个线程局部变量,通过把数据放在ThreadLocal中,可以让每个线程创建一个该变量的副本.也可以看成是线程同步的另一种方式吧,通过为每个线程创建一个变量的线程本地副本 ...
- 【01-14】java ThreadLocal工具类
自定义ThreadLocal package concurrent; import java.util.HashMap; import java.util.Map; /** * @author alo ...
- Java ThreadLocal 理解
ThreadLocal 概念: ThreadLocal不是用来解决对象共享访问的问题,而主要是提供了保存对象的方法和避免参数传递的方便的对象访问方式. ThreadLocal并不是一个Thread,而 ...
- Java ThreadLocal的使用案例
本文以数据库操作Dao为例进行描述ThreadLocal的使用,如下是一个反例: package com.daxin.threadlocal.dao; import java.sql.Connecti ...
- 理解Java ThreadLocal
ThreadLocal是什么 早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地 ...
- Java ThreadLocal (Java代码实战-006)
ThreadLocal解决什么问题 由于 ThreadLocal 支持范型,如 ThreadLocal< StringBuilder >,为表述方便,后文用 变量 代表 ThreadLoc ...
随机推荐
- CopyOnWriteArrayList笔记
CopyOnWriteArrayList笔记 一.前言 Java 5.0 在java.util.concurrent 包中提供了多种并发容器类来改进同步容器的性能. ConcurrentHashMap ...
- 并发新特性—Executor框架与线程池
http://blog.csdn.net/ns_code/article/details/17465497 Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的AP ...
- jQuery实现发送验证码30s倒计时,且刷新页面时有效
在这里讲一讲这个案例的实现思路吧(个人见解)..核心思想:为防止页面刷新时倒计时失效的解决方案是:当每次刷新一次页面时都执行一个函数 即下面讲到的 setStyle() 函数.这个函数会根据当前的 c ...
- Java多线程的中断原理和 interrupt() 几个方法简介
上节讲到,线程被 wait() 通知后进入等待池,可以由本线程的 interrupt() 方法解救,使本线程可以去重新竞争锁等等.是如何实现的呢? 实际上,中断仅仅是在线程对象做一个标记而已,称为中断 ...
- 洛谷 P3627 【抢掠计划】
题库:洛谷 题号:3627 题目:抢掠计划 link:https://www.luogu.org/problem/P3627 思路 : 这道题是一道Tarjan + 最长路的题.首先,我们用Tarja ...
- Linux中安装PostgreSQL-10.1
环境说明 Linux版本:CentOS Linux release 7.6.1810 (Core) PostgreSQL版本:PostgreSQL-10.1 PostgreSQL下载网址:https: ...
- 09 Scrapy框架在爬虫中的使用
一.简介 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架.它集成高性能异步下载,队列,分布式,解析,持久化等. Scrapy 是基于twisted框架开发而来,twisted是一个 ...
- Badboy运行脚本 - 登录QQ邮箱,编写及发送邮件
参考: http://leafwf.blog.51cto.com/872759/1112128 http://www.51testing.com/html/00/130600-1367743.html ...
- codeforces 813 D. Two Melodies(dp)
题目链接:http://codeforces.com/contest/813/problem/D 题意:求两个不相交的子集长度之和最大是多少,能放入同一子集的条件是首先顺序不能变,然后每一个相邻的要么 ...
- 【Offer】[57-2] 【和为S的连续正数序列】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数).例如,输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以 ...