文章导读:

早在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语法与源码分析的更多相关文章

  1. 鸿蒙内核源码分析(GN应用篇) | GN语法及在鸿蒙的使用 | 百篇博客分析OpenHarmony源码 | v60.01

    百篇博客系列篇.本篇为: v60.xx 鸿蒙内核源码分析(gn应用篇) | gn语法及在鸿蒙的使用 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙 ...

  2. ABP源码分析六:依赖注入的实现

    ABP的依赖注入的实现有一个本质两个途径:1.本质上是依赖于Castle这个老牌依赖注入的框架.2.一种实现途径是通过实现IConventionalDependencyRegistrar的实例定义注入 ...

  3. gRPC源码分析0-导读

    gRPC是Google开源的新一代RPC框架,官网是http://www.grpc.io.正式发布于2016年8月,技术栈非常的新,基于HTTP/2,netty4.1,proto3.虽然目前在工程化方 ...

  4. 史上最全的 Redux 源码分析

    前言 用 React + Redux 已经一段时间了,记得刚开始用Redux 的时候感觉非常绕,总搞不起里面的关系,如果大家用一段时间Redux又看了它的源码话,对你的理解会有很大的帮助.看完后,在回 ...

  5. jQuery 2.0.3 源码分析 事件绑定 - bind/live/delegate/on

    事件(Event)是JavaScript应用跳动的心脏,通过使用JavaScript ,你可以监听特定事件的发生,并规定让某些事件发生以对这些事件做出响应 事件的基础就不重复讲解了,本来是定位源码分析 ...

  6. jQuery-1.9.1源码分析系列(十六)ajax——响应数据处理和api整理

    ajax在得到请求响应后主要会做两个处理:获取响应数据和使用类型转化器转化数据 a.获取响应数据 获取响应数据是调用ajaxHandleResponses函数来处理. ajaxHandleRespon ...

  7. Struts2 源码分析——DefaultActionInvocation类的执行action

    本章简言 上一章讲到关于拦截器的机制的知识点,让我们对拦截器有了一定的认识.我们也清楚的知道在执行用户action类实例之前,struts2会先去执行当前action类对应的拦截器.而关于在哪里执行a ...

  8. Struts2 源码分析——配置管理之PackageProvider接口

    本章简言 上一章讲到关于ContainerProvider的知识.让我们知道struts2是如何注册相关的数据.也知道如何加载相关的配置信息.本章笔者将讲到如何加载配置文件里面的package元素节点 ...

  9. angular源码分析:angular中脏活累活承担者之$parse

    我们在上一期中讲 $rootscope时,看到$rootscope是依赖$prase,其实不止是$rootscope,翻看angular的源码随便翻翻就可以发现很多地方是依赖于$parse的.而$pa ...

随机推荐

  1. vue2.0:(八)、外卖App弹窗部分知识点总结

    本篇文章是对外卖App弹窗部分知识点的总结. 知识点一:如何从接口取出不同的图片. 答: 1.header.vue: 代码: <ul v-if="seller.supports&quo ...

  2. 不小心踩到的XMAPP的N种问题

    1.在win10上的xampp集成环境中安装mongo扩展 按照网上搜索的下载对应文件后,在phpinfo里面还是找不到mongo的扩展信息,后面也是请教同事帮忙解决: http://www.theg ...

  3. 对Yii 2.0模型rules的理解(load()无法正确装载数据)

    在实际开发中,遇到数据表新增字段而忘记了在对应模型中rules规则中添加新增的字段,而导致load()方法装载不到新增字段,导致新增字段无法写入数据库中.   解决办法:在新增字段后及时在对应模型ru ...

  4. Swing---WindowConstants

    Java桌面开发过程中,很多人都写过类似下面的代码. import javax.swing.JFrame; public class SimpleFrame { public static void ...

  5. SharePoint 2013 缺少站点保存为模板选项

    如果您尝试在SharePoint Server 2013中保存站点,我们没有看到“将站点另存为模板”选项,则可能是因为该站点已启用站点发布功能.如 之前文章提到 “SharePoint 2010 缺少 ...

  6. App测试流程及测试点

    1 APP测试基本流程 1.1流程图 接收版本 尽快申请到正式环境下测试 不符 App测试版本送测规范 用户行为统计测试 后台订单统计测试 尽快申请到正式环境下测试 兼容性测试.性能压力测试 功能测试 ...

  7. Nuget~管理自己的包包

    很久很久以前,自己就想有个包包,最近又从网上淘了一个,价格不便宜呢,99块,还是个小腰包,不过作工还算精良,我喜欢的类型,帆布休闲包,可以将我的手机,耳机,水,小烟,小酒,小伞都放里,方便至极,哈哈!

  8. UML各种图总结

    UML(Unified Modeling Language)是一种统一建模语言,为面向对象开发系统的产品进行说明.可视化.和编制文档的一种标准语言.下面将对UML的九种图+包图的基本概念进行介绍以及各 ...

  9. JavaScript实用的例子

    ---恢复内容开始--- 1.发送验证码 <input id="send" type="button" value="发送验证码"&g ...

  10. RabbitMQ 学习资料

    https://www.rabbitmq.com/getstarted.html http://www.cnblogs.com/luxiaoxun/p/3918054.html http://back ...