02_ThreadLocal语法与源码分析
文章导读:
早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序, 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本, 每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本.
视频与源码下载:http://edu.51cto.com/lecturer/index/user_id-9166337.html (代码在视频的附件中)
先来用代码来演示下ThreadLocal强大特性
// 用来来存储与线程相关的变量
public class ThreadLocDemo {
// 用来存储线程名称
private ThreadLocal<String> ts = new ThreadLocal<String>();
// 用来存储线程的ID
private ThreadLocal<Long> tl = new ThreadLocal<Long>(); // 获取当前线程的名称和ID信息
public void set() {
ts.set(Thread.currentThread().getName());
tl.set(Thread.currentThread().getId());
} public String getName() {
return ts.get();
} public Long getId() {
return tl.get();
} public static void main(String[] args) throws Exception {
// 当前线程是主线程
// System.out.println(Thread.currentThread().getName());
// System.out.println(Thread.currentThread().getId()); // 把主线程的信息存储在ThreadLocal中
final ThreadLocDemo demo = new ThreadLocDemo();
demo.set();
// 输出主线程的信息
System.out.println(demo.getName());
System.out.println(demo.getId()); // 创建一个子线程,然后用demo也存储子线程的信息
new Thread(new Runnable() {
public void run() {
// 把子线程的信息存储在ThreadLocal中
demo.set();
// 输出子线程的信息
System.out.println(demo.getName());
System.out.println(demo.getId());
}
}, "xyz").start(); Thread.sleep(1000);
// 输出主线程的信息
System.out.println(demo.getName());
System.out.println(demo.getId());
}
}
从打印结果可以看出主线程与子线程数据的存储,获取是不冲突的
main
1
xyz
9
main
1
ThreadLocal.set源码分析, 通过源码可以看出来,Local为不同的线程创建了自己的ThreadLocalMap对象.数据本质是存储在ThreadLocalMap中
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存储结构分析
static class ThreadLocalMap {
// 存储数据的类型是弱引用
static class Entry extends WeakReference<ThreadLocal> {
Object value;
Entry(ThreadLocal k, Object v) {
super(k);
value = v;
}
}
}
ThreadLocal.get()源码分析. 其实还是先通过线程获取每个线程自己的LocalMap对象,然后从Map对象中获取数据信息
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
总结, 大家注意三点:
- 每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象
- 将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中
- ThreadLocal 不是用来解决共享对象的多线程访问问题的, 它是用来延迟变量的生命周期,后面的事务、缓存都会用到此API
02_ThreadLocal语法与源码分析的更多相关文章
- 鸿蒙内核源码分析(GN应用篇) | GN语法及在鸿蒙的使用 | 百篇博客分析OpenHarmony源码 | v60.01
百篇博客系列篇.本篇为: v60.xx 鸿蒙内核源码分析(gn应用篇) | gn语法及在鸿蒙的使用 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙 ...
- ABP源码分析六:依赖注入的实现
ABP的依赖注入的实现有一个本质两个途径:1.本质上是依赖于Castle这个老牌依赖注入的框架.2.一种实现途径是通过实现IConventionalDependencyRegistrar的实例定义注入 ...
- gRPC源码分析0-导读
gRPC是Google开源的新一代RPC框架,官网是http://www.grpc.io.正式发布于2016年8月,技术栈非常的新,基于HTTP/2,netty4.1,proto3.虽然目前在工程化方 ...
- 史上最全的 Redux 源码分析
前言 用 React + Redux 已经一段时间了,记得刚开始用Redux 的时候感觉非常绕,总搞不起里面的关系,如果大家用一段时间Redux又看了它的源码话,对你的理解会有很大的帮助.看完后,在回 ...
- jQuery 2.0.3 源码分析 事件绑定 - bind/live/delegate/on
事件(Event)是JavaScript应用跳动的心脏,通过使用JavaScript ,你可以监听特定事件的发生,并规定让某些事件发生以对这些事件做出响应 事件的基础就不重复讲解了,本来是定位源码分析 ...
- jQuery-1.9.1源码分析系列(十六)ajax——响应数据处理和api整理
ajax在得到请求响应后主要会做两个处理:获取响应数据和使用类型转化器转化数据 a.获取响应数据 获取响应数据是调用ajaxHandleResponses函数来处理. ajaxHandleRespon ...
- Struts2 源码分析——DefaultActionInvocation类的执行action
本章简言 上一章讲到关于拦截器的机制的知识点,让我们对拦截器有了一定的认识.我们也清楚的知道在执行用户action类实例之前,struts2会先去执行当前action类对应的拦截器.而关于在哪里执行a ...
- Struts2 源码分析——配置管理之PackageProvider接口
本章简言 上一章讲到关于ContainerProvider的知识.让我们知道struts2是如何注册相关的数据.也知道如何加载相关的配置信息.本章笔者将讲到如何加载配置文件里面的package元素节点 ...
- angular源码分析:angular中脏活累活承担者之$parse
我们在上一期中讲 $rootscope时,看到$rootscope是依赖$prase,其实不止是$rootscope,翻看angular的源码随便翻翻就可以发现很多地方是依赖于$parse的.而$pa ...
随机推荐
- Java运算符、引用数据类型、流程控制语句
1运算符 1.1算术运算符 运算符是用来计算数据的符号. 数据可以是常量,也可以是变量. 被运算符操作的数我们称为操作数. 算术运算符最常见的操作就是将操作数参与数学计算: 运算符 运算规则 范例 结 ...
- CSS布局技巧之——各种居中
居中是我们使用css来布局时常遇到的情况.使用css来进行居中时,有时一个属性就能搞定,有时则需要一定的技巧才能兼容到所有浏览器,本文就居中的一些常用方法做个简单的介绍. 注:本文所讲方法除了特别说明 ...
- 像音乐播放App一样移动背景
如果你经常听歌,你会发现歌曲app的背景会随着音乐移动的,从左到右或者从上到下,这种动画虽然简单,但是这里有一个技巧.如果你还不明白这种动效看看下面的demo (更多详细请参考:https://git ...
- PHP的加解密:如何安装ioncube扩展?
一.下载loader-wizard.php(支持php5.3.php5.4.php5.5.php5.6版本) ioncube提供了一个安装的向导程序,可以非常方便的帮助检测php的运行环境,自动给出提 ...
- C# 简单创建和删除文件夹
文章转自http://www.cnblogs.com/pegasus923/archive/2011/01/26/1944838.html C#中对文件夹操作需要用到Directory Class.其 ...
- 洛谷 P2691 逃离
题目描述 一个n×n栅格是由n行和n列顶点组成的一个无向图,如图所示.用(i,j)表示处于第i行第j列的顶点.除了边界顶点(即满足i=1,i=n,j=1或j=n的顶点(i,j)),栅格中的所有其他顶点 ...
- MovieReview—Black Panther(黑豹)
Justice & Evil The night before the night, i saw the latest movie in the Marvel series at JiaH ...
- URAL 2027 URCAPL, Episode 1 (模拟)
题意:给你一个HxW的矩阵,每个点是一个指令,根据指令进行一系列操作. 题解:模拟 #include<cstdio> #include<algorithm> using nam ...
- Spark 配置整理
Spark 的配置有很多,这里一方面总结一下官方文档中的内容,一方面将网上查到的资料中用到的针对特定问题的配置整理一下. 先看一下官网的配置:http://spark.apache.org/docs/ ...
- Understanding NFS Caching
Understanding NFS Caching Filesystem caching is a great tool for improving performance, but it is im ...