java.lang.ThreadLocal源码分析
ThreadLocal类提供线程本地变量,为变量在每个线程创建一个副本,每个线程可以访问自己内部的副本变量。
比如,有这样一个需求,需要为每个线程创建一个独一无二的标识,这个标识在第一次调用ThreadId.get()的时候生成,在随后的调用中不会再改变。
public class ThreadId {
private static final AtomicInteger nextId = new AtomicInteger(0);
private static final ThreadLocal<Integer> threadId =
new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return nextId.getAndIncrement();
}
};
public static int get() {
return threadId.get();
}
}
类声明:
public class ThreadLocal<T> {}
实例变量和相关的一个方法:
//用于ThreadLocalMap
private final int threadLocalHashCode = nextHashCode(); //下一个hash code,从0开始
private static AtomicInteger nextHashCode = new AtomicInteger(); //hash增量
private static final int HASH_INCREMENT = 0x61c88647; //在获取下一个hash code
private static int nextHashCode() {
return nextHashCode.getAndAdd(HASH_INCREMENT);
}
构造方法:
public ThreadLocal() {}
重要的操作:
//线程本地变量的初始化方法,访问修饰符为protected是为了让程序员可以覆盖这个方法,默认是返回null,也就是说默认的线程本地变量值为null
protected T initialValue() {
return null;
}
get操作
//获取当前线程的本地变量
public T get() {
Thread t = Thread.currentThread();//得到当前的线程
ThreadLocalMap map = getMap(t);//根据当前线程获得一个ThreadLocalMap
if (map != null) {//如果不为空
ThreadLocalMap.Entry e = map.getEntry(this);//根据当前对象获得Entry
if (e != null) {//如果本地变量存在,返回值
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
//否则调用setInitialValue方法
return setInitialValue();
}
getMap方法
//返回当前线程的threadLocals变量
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
threadLocals的声明
//其实就是一个ThreadLocalMap类型的变量
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocalMap
//ThreadLocalMap里有Entry内部类,用于存放键值对
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value; Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
.....以下省略
}
setInitialValue方法
private T setInitialValue() {
T value = initialValue();//调用initialValue方法,初始化本地变量的值,如果不覆盖该方法,返回null
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);//根据当前线程获取ThreadLocalMap
if (map != null)//如果map不为空
map.set(this, value);//设置键值对
else
createMap(t, value);//否则创建map
return value;
}
createMap方法
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
至此可以知道ThreadLocal如何为每个线程创建变量副本了,每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,存储以ThreadLocal为键,本地线程变量为值的键值对。
remove操作
//先获取当前线程的ThreadLocalMap,然后删除当前ThreadLocal对象
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
java.lang.ThreadLocal源码分析的更多相关文章
- 【JAVA】ThreadLocal源码分析
ThreadLocal内部是用一张哈希表来存储: static class ThreadLocalMap { static class Entry extends WeakReference<T ...
- java.lang.StringBuffer源码分析
StringBuffer是一个线程安全的可变序列的字符数组对象,它与StringBuilder一样,继承父类AbstractStringBuilder.在多线程环境中,当方法操作是必须被同步,Stri ...
- java.lang.StringBuilder源码分析
StringBuilder是一个可变序列的字符数组对象,它继承自AbstractStringBuilder抽象类.它不保证同步,设计出来的目的是当这个字符串缓存只有单线程使用的时候,取代StringB ...
- java.lang.Runnable 源码分析
子接口:RunnableFuture<V>, RunnableScheduledFuture<V> 实现类:AsyncBoxView.ChildState, ForkJoinW ...
- Java并发编程之ThreadLocal源码分析
## 1 一句话概括ThreadLocal<font face="微软雅黑" size=4> 什么是ThreadLocal?顾名思义:线程本地变量,它为每个使用该对象 ...
- Java多线程学习之ThreadLocal源码分析
0.概述 ThreadLocal,即线程本地变量,是一个以ThreadLocal对象为键.任意对象为值的存储结构.它可以将变量绑定到特定的线程上,使每个线程都拥有改变量的一个拷贝,各线程相同变量间互不 ...
- ThreadLocal源码分析-黄金分割数的使用
前提 最近接触到的一个项目要兼容新老系统,最终采用了ThreadLocal(实际上用的是InheritableThreadLocal)用于在子线程获取父线程中共享的变量.问题是解决了,但是后来发现对T ...
- 并发编程(四)—— ThreadLocal源码分析及内存泄露预防
今天我们一起探讨下ThreadLocal的实现原理和源码分析.首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两 ...
- 并发-ThreadLocal源码分析
ThreadLocal源码分析 参考: http://www.cnblogs.com/dolphin0520/p/3920407.html https://www.cnblogs.com/coshah ...
随机推荐
- HDOJ 1301 Jungle Roads
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1301 //HDOJ1301 #include<iostream>#include<c ...
- HTML目录
1. 表格标记 2. HTML常用标记 3. 博客园添加访问人数统计 4. 如何快速掌握CSS(各种CSS工具) 5. HTTP协议状态码详解(HTTP Status Code)(转)
- 如何避免MVC Model First 设计时添加的DataAnnotation被覆盖掉
结合多方资料做一系统,发现Code First中所有代码要自己写,无法自动生成(暂时没有找到方法,有知道的大能,给指点一下,好像在NuGet中有一个插件可以直接从数据库中生成Code First所需类 ...
- QStyle 新风格的实现
摸索了很久,实际实现才发现很简单. 利用qt助手搜style可以发现style的实现和qapplication有关,在Qapplication里面搜到函数: void QApplication:: ...
- QThread与QWidget使用
本文主要内容: 在任务一中,用 四 种方式实现:点击界面按钮,开线程运行一段程序,结果显示在一个Label上.1. 用不正确的方式得到看似正确的结果2. 用Qt Manual 和 例子中使用的方法3. ...
- Linux上安装Mysql+Apache+Php
一.安装Mysql 1.卸载默认的mysql yum -y remove mysql-libs-* Removed: mysql-libs.x86_64 0:5.1.73-3.el6_5 卸载成功 ...
- python 操作word文档
因为工作需要操作一些word文档,记录一下学习思路 #-*- encoding: utf8 -*- import win32com from win32com.client import Dispat ...
- Communications link failure的解决办法
使用Connector/J连接MySQL数据库,程序运行较长时间后就会报以下错误: Communications link failure,The last packet successfully r ...
- JAVA中的deflate压缩实现
在文件的传输过程中,为了使大文件能够更加方便快速的传输,一般采用压缩的办法来对文件压缩后再传输,JAVA中的java.util.zip包中的Deflater和Inflater类为使用者提供了DEFLA ...
- oracle数据操纵语言(DML)data manipulation language
数据库操纵语言(DML)用于查询和操纵模式对象中的数据,它不隐式地提交当前事务. SELECTINSERTUPDATEDELETECALLEXPLAIN PLANLOCK TABLEMERGE使用算术 ...