Java多线程基础(十三)——Thread-Specific Storage(ThreadLocal)模式
一、定义
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)模式相关推荐
- Java多线程干货系列(1):Java多线程基础
转载自 Java多线程干货系列(1):Java多线程基础 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学 ...
- JAVA多线程基础篇-关键字synchronized
1.概述 syncronized是JAVA多线程开发中一个重要的知识点,涉及到多线程开发,多多少少都使用过.那么syncronized底层是如何实现的?为什么加了它就能实现资源串行访问?本文将基于上述 ...
- 爬梯:Java多线程基础
学习资源:狂神说 Java多线程基础 1.多线程概述 Process 进程 一个进程可以有多个线程. Thread 线程 线程就是独立的执行路径 在程序运行时,即使没有自己创建线程,后台也会有多个线程 ...
- java多线程基础学习[狂神说java-多线程笔记]
java多线程基础学习 一.线程简介 1.类比 2.程序进程线程 3.线程的核心概念 二.线程的实现(重点) 调用方法与调用多线程的区别 Thread 类 1.thread使用方法 2. 代码实现 3 ...
- java多线程基础视频_【No996】2020年最新 Java多线程编程核心基础视频课程
01.课程介绍.mp4 02.多线程编程基础-进程与线程.mp4 03.多线程编程基础-使用多线程-继承Thread类.mp4 04.多线程编程基础-使用多线程-实现Runnable接口.mp4 05 ...
- Java多线程干货系列—(一)Java多线程基础
前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ...
- 一篇文章弄懂Java多线程基础和Java内存模型
文章目录 一.多线程的生命周期及五种基本状态 二.Java多线程的创建及启动 1.继承Thread类,重写该类的run()方法 2.通过实现Runnable接口创建线程类 3.通过Callable和F ...
- Java多线程基础知识(一)
Java多线程 一.Java线程模型 实现线程有三种方式:使用内核线程实现.使用用户线程实现和使用用户线程加轻量级进程混合实现.内核线程是直接由操作系统内核支持的线程,通过内核完成线程切换,内核通过操 ...
- Java多线程基础(一)
文章分两份,第一份主要内容为1-4点 1.多线程的概念 2.Java程序运行原理 3.实现多线程的2种方式 4.2种方式的区别 5.线程同步(同步锁) 6.同步线程之间的通讯 1.多线程的概念 (1) ...
- Java多线程基础知识
多线程基础知识 这是我再次学习多线程知识的一个总结,对于刚刚接触的学习者是比较友好易懂的,便于快速的理解和掌握. 一.基本概念: 1.进程:进程就是运行中的程序,当一个程序开始执行,操作系统就会给这个 ...
最新文章
- Anaconda入门使用指南(二)
- 【Netty】 异步任务调度 ( TaskQueue | ScheduleTaskQueue | SocketChannel 管理 )
- ucos操作系统的内核有哪些调度方法
- c++ 程序时间运算 函数;
- bzoj1230[Usaco2008 Nov]lites 开关灯*
- 如何通过序列化在网络间传递对象,网络协议:轻松定义自己的网络通讯协议
- 理解图像中的低频分量和高频分量
- python中@staticmethod_Python中的 @staticmethod@classmethod方法
- C# 最简单的异步委托
- 从用户端到后台系统,严选分销教会我这些事
- secureCRT连接Linux虚拟机
- 当当网上书店购物车——源码
- POST请求 status 415错误解决方法
- kubernetes 非安全部署
- 今天开始写博客记录程序媛成长过程
- 计算机高考计划,职中高三计算机高考复习计划
- 简单理解通大查询下学期课表原理
- pagefile.sys删除
- 【Ubuntu】虚拟机屏幕大小共享文件
- 使用完整拼音查找汉字(完整拼音,不是网上散布的首字符拼音那种方法)