一、定义

Thread - Specific Storage就是“线程独有的存储库”,该模式会对每个线程提供独有的内存空间。

java.lang.ThreadLocal类提供了该模式的实现,ThreadLocal的实例是一种集合(collection)架构,该实例管理了很多对象,可以想象成一个保管有大量保险箱的房间。

java.lang.ThreadLocal类的方法:

  • public void set()

该方法会检查当前调用线程,默认以该线程的Thread.currentThread()值作为键,来保存指定的值。

  • public Object get()

该方法会检查当前调用线程,默认以该线程的Thread.currentThread()值作为键,获取保存指定的值。

二、模式案例

TSLog类:

package Entity;import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
// 实际执行记录日志的类,每个线程都会拥有一个该类的实例
public class TSLog {private PrintWriter writer = null;public TSLog(String fileName) {try {writer = new PrintWriter(new FileWriter(fileName));} catch (IOException e) {e.printStackTrace();}}public void println(String e) {writer.println(e);}public void close() {writer.println("****** End of log");writer.close();}
}

Log类:

package Entity;public class Log {private static final ThreadLocal<TSLog> TS_LOG_THREAD_LOCAL = new ThreadLocal<>();public static void println(String s) {getTSLog().println(s);}public static void close() {getTSLog().close();}private static TSLog getTSLog() {TSLog tsLog = TS_LOG_THREAD_LOCAL.get();if (tsLog == null) {tsLog = new TSLog(Thread.currentThread() + "-log.txt");TS_LOG_THREAD_LOCAL.set(tsLog);}return tsLog;}
}

ClientThread类:

package Entity;public class ClientThread extends Thread{public ClientThread(String name) {super(name);}@Overridepublic void run() {System.out.println(getName() + " BEGIN");for (int i = 0; i < 10; i++) {Log.println("i=" + i);try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}Log.close();System.out.println(getName() + " END");}
}

main类:

import Entity.ClientThread;public class Demo2 {public static void main(String[] args) {new ClientThread("Alice").start();new ClientThread("Bobby").start();new ClientThread("Chris").start();}
}

三、模式讲解

Thread-Specific Storage模式的角色如下:

  • Client(委托人)参与者

Client参与者会将工作委托给TSObjectProxy参与者。(案例中的ClientThread类就是Client)

  • TSObjectProxy(线程独有对象的代理者)参与者

TSObjectProxy参与者会处理多个Client委托的工作。(案例中的Log类就是TSObjectProxy)

  • TSObjectCollection(线程独有对象的集合)参与者

(案例中的java.lang.ThreadLocal类就是TSObjectCollection)

  • TSObject(线程独有的对象)参与者

TSObject存放线程所特有的信息,TSObject实例的方法只会由单线程调用,由TSObjectCollection管理,每个线程独都拥有独自的TSObject实例。(案例中的TSLog类就是TSObject)

四、ThreadLocal的原理

ThreadLocal类主要有四个方法:

1、初始化返回值的方法:

该方法实现只返回null,并且修饰符为protected,很明显,如果用户想返回初始值不为null,则需要重写该方法;

protected T initialValue() {return null;}

2、get方法,获取线程本地副本变量

public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}return setInitialValue();}

3、set方法,设置线程本地副本变量

public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);}

4、remove方法,移除线程本地副本变量

public void remove() {ThreadLocalMap m = getMap(Thread.currentThread());if (m != null)m.remove(this);}

如果需要我们自己来设计ThreadLocal对象,那么,一般的实现思路:

设计一个线程安全的Map,key就是当前线程对象,Value就是线程本地变量的值。

然而,JDK的实现思路:

让每个Thread对象,自身持有一个Map,这个Map的Key就是当前ThreadLocal对象,Value是本地线程变量值。相对于加锁的实现方式,这样做可以提升性能,其实是一种以空间换时间的思路。

ThreadLocal类有一个getMap()方法,其实就是返回Thread对象自身的Map——threadLocals。

ThreadLocalMap getMap(Thread t) {return t.threadLocals;}

threadLocals是一种ThreadLocal.ThreadLocalMap类型的数据结构,作为内部类定义在ThreadLocal类中,其内部采用一种WeakReference的方式保存键值对。

深入解析J.U.C并发包(十五)—— Thread - Specific Storage(ThreadLocal)模式相关推荐

  1. 云计算设计模式(十五)——管道和过滤器模式

    云计算设计模式(十五)--管道和过滤器模式 分解,执行复杂处理成一系列可重复使用分立元件的一个任务.这种模式可以允许执行的处理进行部署和独立缩放任务元素提高性能,可扩展性和可重用性. 背景和问题 一个 ...

  2. JAVA架构师之路十五:设计模式之策略模式

    JAVA架构师之路十四:设计模式之模板模式 策略模式 1. 策略模式 2. 优惠券案例 3. 支付案例 人生的游戏不在于拿了一副好牌,而在于怎样去打好坏牌,世上没有常胜将军,勇于超越自我者才能得到最后 ...

  3. 设计模式(十五):Iterator迭代器模式 -- 行为型模式

    1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的有用方法,但通常你会处理一组对象或者集合. 集合不一定是均一的.图形用 ...

  4. 第十五节: EF的CodeFirst模式通过DataAnnotations修改默认协定

    一. 简介 1. DataAnnotations说明:EF提供以特性的方式添加到 domain classes上,其中包括两类:  A:System.ComponentModel.DataAnnota ...

  5. Android设计模式(十五)--备忘录模式

    在Android中用于保存Activity状态的onSaveInstanceState()和恢复Activity状态的onRestoreInstanceState(), 这样的算不算是一种备忘录模式呢 ...

  6. 初学 Java 设计模式(十五):实战命令模式 「扫码点餐」

    一.命令模式介绍 1. 解决的问题 主要解决在系统中,行为请求者和行为实现者紧耦合的问题. 2. 定义 命令模式是一种行为设计模式,它可将请求转换为一个包含与请求相关的所有信息的独立对象.这个转换会根 ...

  7. 设计模式十五:行为型-命令模式

    行为型模式:命令模式 文章目录 行为型模式:命令模式 命令模式 1.命令模式:介绍 2.命令模式:模拟场景 3.命令模式:代码实现 4.命令模式:总结 命令模式 1.命令模式:介绍 命令模式 把逻辑实 ...

  8. 维度模型数据仓库(十五) —— 多重星型模式

    (五)进阶技术         10. 多重星型模式         从(五)进阶技术1.  "增加列"开始,已经通过增加列和表扩展了数据仓库,在(五)进阶技术5. "快 ...

  9. JavaScript 设计模式学习第二十五篇-中介者模式

    中介者模式(Mediator Pattern)又称调停模式,使得各对象不用显式地相互引用,将对象与对象之间紧密的耦合关系变得松散,从而可以独立地改变他们.核心是多个对象之间复杂交互的封装. 根据最少知 ...

  10. Xilinx FPGA资源解析与使用系列——Transceiver(十)PRBS、RX Equalizer、CDR

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Xilinx FPGA资源解析与使用系列--Transceiver(十)PRBS.RX Equalizer.CDR PRBS测试序列 ...

最新文章

  1. eclipse添加缺失的包/src/main/resource
  2. 在国企当程序员是怎么样的体验?
  3. 【Android 应用开发】 自定义 圆形进度条 组件
  4. 为什么我启动哪一个tomcat都是启动同一个tomcat(tomcat7)
  5. OpenGL使用计算着色器进行布料模拟
  6. 『设计模式』简单工厂模式
  7. 月薪30K程序员花了一个小时,用c++做出经典扫雷游戏 !
  8. java 打印_剑指Offer面试题20(Java版):顺时针打印矩阵
  9. SLAM Cartographer(18)后端优化问题求解器
  10. 大道至简 第二章 读后随笔
  11. bzoj 2553 [BeiJing2011]禁忌——AC自动机+概率DP+矩阵
  12. 析构函数的标量与矢量?
  13. 剖析WordPress模板文件【转】
  14. 编译OpenJDK8:OpenJDK8与OpenJDK8u运行结果相差很大
  15. 西威变频器使用说明书_西威变频器说明书 (1)
  16. 为什么小角度的弧度值可以近似等于正切值或者正弦值?
  17. 移动端高度兼容iPhoneX
  18. jike2012年5月实习题
  19. Windows命令行解决8080端口被占用
  20. 淘宝手淘首页金字塔流量爬升法|运营狗

热门文章

  1. manjaro 配置 独立显卡驱动
  2. [每日一氵] openCV drawMatches 函数中 flag 用法
  3. 动态随机存储器的刷新
  4. 还在用git commit -m 吗?Git 提交规范和自动产生changelog手摸手教程。
  5. 动态改变图片的useMap属性导致IE假死或崩溃!
  6. 2019 9月 月末总结
  7. 微信公众号上传永久图片素材(将阿里云图片上传至微信公众号图片素材)
  8. **********模拟新浪微博*********
  9. 爬取豆瓣电影数据并进行分析可视化
  10. 笔记本搜不到WiFi是什么原因