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 ...
随机推荐
- 对javascript this的理解
对于this的理解,大部分时间都比较模糊,最近几天做了一些研究,记录一下 首先应该明白,this是执行上下文的一个属性,它的值取决于执行上下文,执行上下文和函数调用方式相关,定义一个function的 ...
- 关于egg的压缩测试报告
167274doc 单字分词 全压缩 时间 real 15m58.464suser 13m52.157ssys 2m3.445s 空间 tmpfs 12G 1.5G 11G 13% /ape ...
- ubuntu13.04装配oracle11gR2
http://jingyan.baidu.com/album/bea41d435bc695b4c41be648.html?picindex=2 http://www.360doc.com/conten ...
- eclipse中的tomcat debug模式启动报超时45s
在eclipse中加入tomcat,开debug模式非常好用,这里就不介绍了 最近eclipse的tomcat开debug模式就是启动不了,增加时间也不能解决,但是非debug模式就可以打开,我觉得是 ...
- Linux上安装Mysql+Apache+Php
一.安装Mysql 1.卸载默认的mysql yum -y remove mysql-libs-* Removed: mysql-libs.x86_64 0:5.1.73-3.el6_5 卸载成功 ...
- SQL操作XML
前面一段时间为了赶项目的进度,一直在加班,现在空闲了下来将前面碰到的问题整理了一下,发现了一些十分有用的,在此记录下来,看能不能帮助到遇到同样问题的朋友,此文仅是自己个人的意见,若存在问题,还望不宁赐 ...
- MyBatis优化技巧
☬配置日志文件 封装工具类 代码贴一下: package com.shxt.utils; import java.io.InputStream; import org.apache.ibatis.io ...
- 通过继承nsoperation的方法--处理复杂任务
#import <Foundation/Foundation.h> @class TTOperation; @protocol TTOperationDelegate <NSObje ...
- C++重载自增/减操作符
作为类成员使用. 前缀是先加/减1,再取值:后缀是先取值,再加/减1. 前缀是左值,返回引用:后缀是右值,返回值. 后缀多一个int参数进行区分,用时编译器会传个没用的0作实参. 在后缀实现中调用前缀 ...
- Android小项目之七 应用程序的更新安装
------- 源自梦想.永远是你IT事业的好友.只是勇敢地说出我学到! ---------- 按惯例,写在前面的:可能在学习Android的过程中,大家会和我一样,学习过大量的基础知识,很多的知识点 ...