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源码分析的更多相关文章

  1. 【JAVA】ThreadLocal源码分析

    ThreadLocal内部是用一张哈希表来存储: static class ThreadLocalMap { static class Entry extends WeakReference<T ...

  2. java.lang.StringBuffer源码分析

    StringBuffer是一个线程安全的可变序列的字符数组对象,它与StringBuilder一样,继承父类AbstractStringBuilder.在多线程环境中,当方法操作是必须被同步,Stri ...

  3. java.lang.StringBuilder源码分析

    StringBuilder是一个可变序列的字符数组对象,它继承自AbstractStringBuilder抽象类.它不保证同步,设计出来的目的是当这个字符串缓存只有单线程使用的时候,取代StringB ...

  4. java.lang.Runnable 源码分析

    子接口:RunnableFuture<V>, RunnableScheduledFuture<V> 实现类:AsyncBoxView.ChildState, ForkJoinW ...

  5. Java并发编程之ThreadLocal源码分析

    ## 1 一句话概括ThreadLocal<font face="微软雅黑" size=4>  什么是ThreadLocal?顾名思义:线程本地变量,它为每个使用该对象 ...

  6. Java多线程学习之ThreadLocal源码分析

    0.概述 ThreadLocal,即线程本地变量,是一个以ThreadLocal对象为键.任意对象为值的存储结构.它可以将变量绑定到特定的线程上,使每个线程都拥有改变量的一个拷贝,各线程相同变量间互不 ...

  7. ThreadLocal源码分析-黄金分割数的使用

    前提 最近接触到的一个项目要兼容新老系统,最终采用了ThreadLocal(实际上用的是InheritableThreadLocal)用于在子线程获取父线程中共享的变量.问题是解决了,但是后来发现对T ...

  8. 并发编程(四)—— ThreadLocal源码分析及内存泄露预防

    今天我们一起探讨下ThreadLocal的实现原理和源码分析.首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两 ...

  9. 并发-ThreadLocal源码分析

    ThreadLocal源码分析 参考: http://www.cnblogs.com/dolphin0520/p/3920407.html https://www.cnblogs.com/coshah ...

随机推荐

  1. 转:关掉Archlinux中烦人的响铃

    http://www.0597seo.com/?p=461 F**K,在Archlinux中,每当在听音乐,声音开得挺大的,忽然在控制台输错了命令,那可恶的该死的警告声猛的一下总是吓的我精神晃晃(这是 ...

  2. 【源码】初探C#爬虫,持续更新中。。。

       最近看到园子里有人用python做的爬虫软件并且上传的源码,苦于不懂python,便想着用C#也实现一个简易的爬虫软件.于是昨晚花了一个多小时的时间实现了一个简单的爬虫软件,功能十分简单,但是觉 ...

  3. 最近在用placeholder ,是已有的,网上也有不少都是jq写的

    其实除了支持placeholder 的浏览器,其他用js 或jq实现的都不叫placeholder 效果,只能算上是获取焦点,或失去焦点时的一个placeholder 没有出生时就已经存在效果 很多人 ...

  4. IOS开发UI篇之自动滚动图片

    我们在做项目是有时候会遇到设置自动滚动图片,所以我自己也遇到过两次.觉得他是一个挺有意思东西,所以做了下总结 DEMO: .h #import <UIKit/UIKit.h> @inter ...

  5. MS SQL SERVER 中的系统表

    MS SQL SERVER 中的系统表 序号 名称 说明 备注 1 syscolumns 每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行.   2 syscomments 包含每 ...

  6. web前端开发(6)

    为了避免全局变量泛滥导致冲突,最简单有效的办法是用匿名函数将脚本包起来,让变量的作用域控制在函数之内.

  7. 使用JSON进行数据传输的总结

    一.选择的意义 在异步应用程序中发送和接收信息时,可以选择以纯文本和 XML 作为数据格式.为了更好的使用ajax, 我们将学习一种有用的数据格式 JavaScript Object Notation ...

  8. 转 【O2O案例】汽车后市场垂直化电子商务:平业模式解析

    核心提示:一.商业模式简介.汽车后市场垂直化电子商务是我在2010年初开始筹划,起因是在淘宝工作期间运营汽车类目后遇到很多问题无决,由于 一.商业模式简介. 汽车后市场垂直化电子商务是我在2010年初 ...

  9. 用jquery 实现 超出字符 截断加上省略号并且可以提示全部内容

    1.test.jsp Java代码 <%@ page language="java" pageEncoding="UTF-8"%> <html ...

  10. SourceTree基本操作

    下载地址:https://www.sourcetreeapp.com 1.从克隆远程仓库 2.填写git地址 3.克隆成功后会来点如下界面,点击testGitHub 4.scourceTree管理界面 ...