一、定义

Thread-Specific Storage就是“线程独有的存储库”,该模式会对每个线程提供独有的内存空间。
java.lang.ThreadLocal类提供了该模式的实现,ThreadLocal的实例是一种集合(collection)架构,该实例管理了很多对象,可以想象成一个保管有大量保险箱的房间。

java.lang.ThreadLocal类的方法:

  • public void set()

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

  • public Object get()

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

二、模式案例

TSLog类:

//实际执行记录日志的类,每个线程都会拥有一个该类的实例
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 s) {writer.println(s);}public void close() {writer.println("==== End of log ====");writer.close();}
}

Log类:

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

ClientThread类:

public class ClientThread extends Thread {public ClientThread(String name) {super(name);}public 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) {}}Log.close();System.out.println(getName() + " END");}
}

执行:
Alice、Bobby、Chris三个线程调用Log类的同一个方法,但实际上每个线程都拥有独自的TSLog实例。

public class Main {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) {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的方式保存键值对。

Java多线程基础(十三)——Thread-Specific Storage(ThreadLocal)模式相关推荐

  1. Java多线程干货系列(1):Java多线程基础

    转载自  Java多线程干货系列(1):Java多线程基础 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学 ...

  2. JAVA多线程基础篇-关键字synchronized

    1.概述 syncronized是JAVA多线程开发中一个重要的知识点,涉及到多线程开发,多多少少都使用过.那么syncronized底层是如何实现的?为什么加了它就能实现资源串行访问?本文将基于上述 ...

  3. 爬梯:Java多线程基础

    学习资源:狂神说 Java多线程基础 1.多线程概述 Process 进程 一个进程可以有多个线程. Thread 线程 线程就是独立的执行路径 在程序运行时,即使没有自己创建线程,后台也会有多个线程 ...

  4. java多线程基础学习[狂神说java-多线程笔记]

    java多线程基础学习 一.线程简介 1.类比 2.程序进程线程 3.线程的核心概念 二.线程的实现(重点) 调用方法与调用多线程的区别 Thread 类 1.thread使用方法 2. 代码实现 3 ...

  5. java多线程基础视频_【No996】2020年最新 Java多线程编程核心基础视频课程

    01.课程介绍.mp4 02.多线程编程基础-进程与线程.mp4 03.多线程编程基础-使用多线程-继承Thread类.mp4 04.多线程编程基础-使用多线程-实现Runnable接口.mp4 05 ...

  6. Java多线程干货系列—(一)Java多线程基础

    前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ...

  7. 一篇文章弄懂Java多线程基础和Java内存模型

    文章目录 一.多线程的生命周期及五种基本状态 二.Java多线程的创建及启动 1.继承Thread类,重写该类的run()方法 2.通过实现Runnable接口创建线程类 3.通过Callable和F ...

  8. Java多线程基础知识(一)

    Java多线程 一.Java线程模型 实现线程有三种方式:使用内核线程实现.使用用户线程实现和使用用户线程加轻量级进程混合实现.内核线程是直接由操作系统内核支持的线程,通过内核完成线程切换,内核通过操 ...

  9. Java多线程基础(一)

    文章分两份,第一份主要内容为1-4点 1.多线程的概念 2.Java程序运行原理 3.实现多线程的2种方式 4.2种方式的区别 5.线程同步(同步锁) 6.同步线程之间的通讯 1.多线程的概念 (1) ...

  10. Java多线程基础知识

    多线程基础知识 这是我再次学习多线程知识的一个总结,对于刚刚接触的学习者是比较友好易懂的,便于快速的理解和掌握. 一.基本概念: 1.进程:进程就是运行中的程序,当一个程序开始执行,操作系统就会给这个 ...

最新文章

  1. Anaconda入门使用指南(二)
  2. 【Netty】 异步任务调度 ( TaskQueue | ScheduleTaskQueue | SocketChannel 管理 )
  3. ucos操作系统的内核有哪些调度方法
  4. c++ 程序时间运算 函数;
  5. bzoj1230[Usaco2008 Nov]lites 开关灯*
  6. 如何通过序列化在网络间传递对象,网络协议:轻松定义自己的网络通讯协议
  7. 理解图像中的低频分量和高频分量
  8. python中@staticmethod_Python中的 @staticmethod@classmethod方法
  9. C# 最简单的异步委托
  10. 从用户端到后台系统,严选分销教会我这些事
  11. secureCRT连接Linux虚拟机
  12. 当当网上书店购物车——源码
  13. POST请求 status 415错误解决方法
  14. kubernetes 非安全部署
  15. 今天开始写博客记录程序媛成长过程
  16. 计算机高考计划,职中高三计算机高考复习计划
  17. 简单理解通大查询下学期课表原理
  18. pagefile.sys删除
  19. 【Ubuntu】虚拟机屏幕大小共享文件
  20. 使用完整拼音查找汉字(完整拼音,不是网上散布的首字符拼音那种方法)

热门文章

  1. 服装erp软件如何提高企业利润
  2. 谈谈应聘阿里全流程(良心之作,好评满满)
  3. 有符号数的二进制表示方式
  4. 9个offer,12家公司,35场面试,从微软到谷歌
  5. 一小时建立数据分析平台
  6. 动画云渲染【渲染101】渲染小提示
  7. OpenGL ES 2 0 (iOS)[05 1]:进入 3D 世界,从正方体开始
  8. 29、域名ICP备案查询API接口,免费好用
  9. Enrico Da Vincent
  10. txt音乐播放器PC版免费下载(包含C程序源码与exe文件)