ThreadLocal的介绍与使用
本篇是《图解Java多线程设计模式》第十一章的读书笔记。
有一个储物室,里面有很多储物柜。每个人拿着自己的钥匙去开自己的储物柜,虽然进同一个储物室,但彼此互不干扰。这就是 Thread-Local Storage 线程中的局部存储空间。
来看一个例子:每个线程将信息打印到自己的日志文件中。
TSLog :打印类,每个线程都有自己的 TSLog 对象,向自己的日志文件中打印信息。
public class TSLog {private PrintWriter writer;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() {System.out.println("=====End of log======");writer.close();}
}
Log:利用 ThreadLocal 获取请求对应的 TSLog 对象。
public class Log {private static final ThreadLocal<TSLog> tsLogCollection = new ThreadLocal<>();private static TSLog getTSLog() {TSLog tsLog = tsLogCollection.get();if (tsLog == null) {tsLog = new TSLog(Thread.currentThread().getName()+"-log.txt");tsLogCollection.set(tsLog);}return tsLog;}public static void println(String s) {getTSLog().println(s);}public static void close() {getTSLog().close();}
}
ClientThread:请求线程
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:测试
public class Main {public static void main(String[] args) {new ClientThread("Zhao").start();new ClientThread("Qian").start();new ClientThread("Sun").start();}
}
类的关系图:
ThreadLocal 是线程特有的存储空间的意思,也就是只属于该线程,各个线程各自专用。
虽然 Thread-local storage 模式没有使用到锁,但这并不意味着吞吐量的提高,因为 ThreadLocal 存储/获取操作会产生额外的性能开销,该模式的重点在于没有显示的执行互斥处理,导致编程时犯错的可能性减小。
由于 ThreadLocal 会自动判断当前的线程,这相当于在程序中引入了上下文,这有一定危险,因为我们看不到处理中所用到的信息。例如在找Bug时,我们关注信息的流向,但上下文的引入导致当前Bug的产生可能是程序之前的行为导致的,也就导致定位问题的难度。
基于角色与基于任务
关于线程与线程使用的信息之间的关系,由基于角色和基于任务两种思考方式。
主体与客体
要想组装塑料模型,以下二者缺一不可。
- 组装塑料模型的人
- 塑料模型套件
同理假设我们需要让线程去完成一项工作,那么以下二者缺一不可:
- 工作的线程
- 工作所需的信息
总结以下就是:
- 用于做某事的主体
- 用于做某事的客体
在设计多线程程序时,根据以 主体 为主还是以 客体 为主的不同产生了以下两种方式
- 基于角色:以主体为主
- 基于任务:以客体为主
基于角色的考虑方式
即”线程最伟大"的方式。线程的实例来保存进行工作所必须的信息(上下文,状态)。这样减少了线程之间的交互信息量。一个线程使用从其它线程接收到的信息来执行处理(指的是线程间的通信),改变自己的内部状态。我们将这种线程称为角色。用代码来表示大致如下:
class Actor extends Thread {// 角色的内部状态public void run() {// 循环的从外部接收并执行任务,改变内部状态}
}
该书的第12章介绍的 Active Object 模式就是一种角色。
基于任务的考虑方式
即“任务最伟大”的方式。信息保存在线程之间交互的实例中。不仅是数据还有请求的方法都在该实例中。我们称该实例为信息,请求或是命令。这里暂称为任务,任务储存了足够的信息,可以说这是一种 富任务 往来于 轻线程之间的方式。典型就是书的第8章介绍的 Worker Thread 模式。
用代码表示大致如下:
class Task implements Runnable {// 进行工作所必须的信息public void run() {// 工作的处理内容}
}
java.util.TimerTask
类就是一个基于任务的类。该类实现了 Runnable 接口,它会被 java.util.Timer
类调用。如果要定义一项在一定时间后进行的工作或是顶起进行的工作,可以使用该类。
java.util.concurrent.FutureTask
类也是一个基于任务的类。
实际上两种方式是综合在一起的
我们通常采用的是 角色之间通过任务交互 的形式。
ThreadLocal的介绍与使用相关推荐
- 线程本地ThreadLocal的介绍与使用!
ThreadLocal简介 我们通过上两篇的学习,我们已经知道了变量值的共享可以使用public static变量的形式,所有的线程都使用同一个被public static修饰的变量. 那么如果我们想 ...
- ThreadLocal知识介绍
ThreadLocal为解决多线程的并发问题提供了一种新的思路,使用这个工具类可以优美的编写出多线程程序. ThreadLocal他不是一个线程,而是线程的一个本地化对象.当工作于多个线程的对象使用T ...
- 深入浅出ThreadLocal,你会吗?
ThreadLocal全面解析 学习目标 了解ThreadLocal的介绍 掌握ThreadLocal的运用场景 了解ThreadLocal的内部结构 了解ThreadLocal的核心方法源码 了解T ...
- threadlocal存连接对象的目的_面试官:知道ThreadLocal嘛?谈谈你对它的理解?
在java的多线程模块中,ThreadLocal是经常被提问到的一个知识点,提问的方式有很多种,可能是循序渐进也可能是就像我的题目那样,因此只有理解透彻了,不管怎么问,都能游刃有余. 这篇文章主要从以 ...
- ThreadLocal 变量和 与线程池配合使用时可能会出现的问题
ThreadLocal 变量和 与线程池配合使用时可能会出现的问题 ThreadLocal 的介绍和使用 先看下ThreadLocal变量的使用 public void set(T value) {T ...
- 揭秘ThreadLocal
ThreadLocal是开发中最常用的技术之一,也是面试重要的考点.本文将由浅入深,介绍ThreadLocal的使用方式.实现原理.内存泄漏问题以及使用场景. ThreadLocal作用 在并发编程中 ...
- Java多线程编程-(4)-线程间通信机制的介绍与使用
上一篇: Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-线程本地Th ...
- 谈谈对ThreadLocal的理解?(基于jdk1.8)
在java的多线程模块中,ThreadLocal是经常被提问到的一个知识点,提问的方式有很多种,可能是循序渐进也可能是就像我的题目那样,因此只有理解透彻了,不管怎么问,都能游刃有余. 这篇文章主要从以 ...
- 由浅入深,全面解析ThreadLocal
文章目录 ThreadLocal全面解析 1. ThreadLocal介绍 1.1 官方介绍 1.2 基本使用 1.2.1 常用方法 1.2.2 使用案例 1.3 ThreadLocal类与synch ...
- 多线程 threadlocal 获取经办人信息
解决hash冲突: 在java线程中,每个线程都有一个ThreadLocalMap实例变量(如果不使用ThreadLocal,不会创建这个Map,一个线程第一次访问某个ThreadLocal变量时,才 ...
最新文章
- Distilling the Knowledge in a Neural Network 论文笔记蒸馏
- 大厂需要这样的Java工程师
- 【字节流处理】linux下uint8转float的注意事项
- 【转】基于Android Fragment功能的例子
- mysql v8 漏洞_mysql'密码安全 - osc_v8gts6gd的个人空间 - OSCHINA - 中文开源技术交流社区...
- hm55主板支持最大内存_内存频率取决于CPU还是主板?内存频率看主板支持还是看CPU支持?...
- 每天三分钟玩转Git(已完结)
- python中str用法_python数据类型之str用法
- 在Windows上构建OpenJDK
- java md2_java中加密的实现方法(MD5,MD2,SHA)
- 口腔取模过程及注意事项_取模变形?教你三种方法,轻松防止取模变形!
- 编程学习记录13:Oracle数据库,表的查询
- 神奇的编码C语言,神奇的fans (C语言代码)
- (66)SPI外设驱动发送驱动(五)(第14天)
- java mvc controller_java之spring mvc之Controller配置的几种方式
- 计算最大值和最小值(分治法)
- 天翼网关密码忘记(猫密码忘记)
- Java主流开发框架
- 从身份证号里可以解析出出生地,年月日,性别及年龄
- 打开jpg显示没有注册类 打开txt显示找不到文件位置 画图板也打不开,总之微软默认的应用都打不开 解决方案如下: