本篇是《图解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的介绍与使用相关推荐

  1. 线程本地ThreadLocal的介绍与使用!

    ThreadLocal简介 我们通过上两篇的学习,我们已经知道了变量值的共享可以使用public static变量的形式,所有的线程都使用同一个被public static修饰的变量. 那么如果我们想 ...

  2. ThreadLocal知识介绍

    ThreadLocal为解决多线程的并发问题提供了一种新的思路,使用这个工具类可以优美的编写出多线程程序. ThreadLocal他不是一个线程,而是线程的一个本地化对象.当工作于多个线程的对象使用T ...

  3. 深入浅出ThreadLocal,你会吗?

    ThreadLocal全面解析 学习目标 了解ThreadLocal的介绍 掌握ThreadLocal的运用场景 了解ThreadLocal的内部结构 了解ThreadLocal的核心方法源码 了解T ...

  4. threadlocal存连接对象的目的_面试官:知道ThreadLocal嘛?谈谈你对它的理解?

    在java的多线程模块中,ThreadLocal是经常被提问到的一个知识点,提问的方式有很多种,可能是循序渐进也可能是就像我的题目那样,因此只有理解透彻了,不管怎么问,都能游刃有余. 这篇文章主要从以 ...

  5. ThreadLocal 变量和 与线程池配合使用时可能会出现的问题

    ThreadLocal 变量和 与线程池配合使用时可能会出现的问题 ThreadLocal 的介绍和使用 先看下ThreadLocal变量的使用 public void set(T value) {T ...

  6. 揭秘ThreadLocal

    ThreadLocal是开发中最常用的技术之一,也是面试重要的考点.本文将由浅入深,介绍ThreadLocal的使用方式.实现原理.内存泄漏问题以及使用场景. ThreadLocal作用 在并发编程中 ...

  7. Java多线程编程-(4)-线程间通信机制的介绍与使用

    上一篇: Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-线程本地Th ...

  8. 谈谈对ThreadLocal的理解?(基于jdk1.8)

    在java的多线程模块中,ThreadLocal是经常被提问到的一个知识点,提问的方式有很多种,可能是循序渐进也可能是就像我的题目那样,因此只有理解透彻了,不管怎么问,都能游刃有余. 这篇文章主要从以 ...

  9. 由浅入深,全面解析ThreadLocal

    文章目录 ThreadLocal全面解析 1. ThreadLocal介绍 1.1 官方介绍 1.2 基本使用 1.2.1 常用方法 1.2.2 使用案例 1.3 ThreadLocal类与synch ...

  10. 多线程 threadlocal 获取经办人信息

    解决hash冲突: 在java线程中,每个线程都有一个ThreadLocalMap实例变量(如果不使用ThreadLocal,不会创建这个Map,一个线程第一次访问某个ThreadLocal变量时,才 ...

最新文章

  1. Distilling the Knowledge in a Neural Network 论文笔记蒸馏
  2. 大厂需要这样的Java工程师
  3. 【字节流处理】linux下uint8转float的注意事项
  4. 【转】基于Android Fragment功能的例子
  5. mysql v8 漏洞_mysql'密码安全 - osc_v8gts6gd的个人空间 - OSCHINA - 中文开源技术交流社区...
  6. hm55主板支持最大内存_内存频率取决于CPU还是主板?内存频率看主板支持还是看CPU支持?...
  7. 每天三分钟玩转Git(已完结)
  8. python中str用法_python数据类型之str用法
  9. 在Windows上构建OpenJDK
  10. java md2_java中加密的实现方法(MD5,MD2,SHA)
  11. 口腔取模过程及注意事项_取模变形?教你三种方法,轻松防止取模变形!
  12. 编程学习记录13:Oracle数据库,表的查询
  13. 神奇的编码C语言,神奇的fans (C语言代码)
  14. (66)SPI外设驱动发送驱动(五)(第14天)
  15. java mvc controller_java之spring mvc之Controller配置的几种方式
  16. 计算最大值和最小值(分治法)
  17. 天翼网关密码忘记(猫密码忘记)
  18. Java主流开发框架
  19. 从身份证号里可以解析出出生地,年月日,性别及年龄
  20. 打开jpg显示没有注册类 打开txt显示找不到文件位置 画图板也打不开,总之微软默认的应用都打不开 解决方案如下:

热门文章

  1. 单模光纤和多模光纤的对比
  2. Ubuntu查看显卡型号
  3. 如何刷百度搜索下拉框进行营销引流?
  4. Flutter笔记(9)flutter中baseline基准线布局
  5. 阅读“变形计”:一场偶然与非偶然的相遇
  6. 支付宝 android sdk 调用h,支付宝 iOS SDK 的简单使用
  7. word实现奇数页页眉用本章标题,偶数页用论文标题
  8. 30个java编程小技巧
  9. OSChina 周一乱弹 ——我们不应歧视任何语言,她们都是萌娘!(有图有真相)...
  10. Junit测试运行出现No tests were found