文章目录

  • 11.1 Thread-Specific Storage模式
  • 11.2 java.lang.ThreadLocal
    • 11.2.1 java.lang.ThreadLocal 就是储物间
    • 11.2.2 java.lang.ThreadLocal 与泛型
  • 11.5 Thread-Specific Storage模式中的角色
    • 11.5.1 Client(委托者)
    • 11.5.2 TSObjectProxy(线程特有的对象的代理人)
    • 11.5.3 TSObjectCollection(线程特有的对象的集合)
    • 11.5.4 TSObject(线程特有的对象)
    • 11.5.5 类图与时序图
  • 11.6 拓展思路的要点
    • 11.6.1 局部变量与 java.lang.ThreadLocal 类
    • 11.6.2 保存线程特有的信息的位置
      • 11.6.2.1 在线程外保存线程特有的信息
      • 11.6.2.2 在线程内保存线程特有的信息
      • 11.6.2.3 总结
    • 11.6.3 不必担心其他线程访问
    • 11.6.4 吞吐量的提高很大程序上取决于实现方式
  • 11.8 基于角色与基于任务
    • 11.8.1 主体与客体
    • 11.8.2 基于角色的考虑方式
    • 11.8.3 基于任务的考虑方式

11.1 Thread-Specific Storage模式

  1. 有一个储物间,里面并排摆放着许多储物柜。一个人拿着自己的钥匙进入了储物间,出来时手上拿着自己的行李。别人也拿着自己的钥匙进入了储物间。但是,虽然进人的是同一个储物间,打开的当然是另外一个储物柜。使用者都会从各自的储物柜中取出自己的行李。
  2. Specific是 “特定的” 的意思,Storage是储存柜、存储装置的意思。因此,所谓 Thread-Specific Storage 就是 “每个线程特有的存储柜”、“为每个线程准备的存储空间” 的意思。
  3. Thread-Specific Storage模式是一种即使只有一个入口,也会在内部为每个线程分配特有的存储空间的模式。

11.2 java.lang.ThreadLocal

11.2.1 java.lang.ThreadLocal 就是储物间

  1. 将 Java.lang.ThreadLocal 的实例当作一种集合可能会有助于大家理解它。也就是说,一个ThreadLocal的实例会管理多个对象
  2. ThreadLocal 类的 set 方法用于将通过参数接收的实例与调用该方法的线程(当前线程)对应并存储起来。这里存储的对象可以通过get方法获取。set方法中没有表示线程的参数。set方法会先查询当前线程(即表达式Thread.currentThread()的值),然后以它作为键来存储实例。
  3. ThreadLocal 类的 get 方法用于获取与调用 get 方法的线程(当前线程)对应的实例。该线程之前通过 set 方法存储的实例就是 get 方法的返回值。如果之前一次都还没有调用过 set 方法,则 get方法的返回值为null。

11.2.2 java.lang.ThreadLocal 与泛型

  1. java.lang.ThreadLocal是一个泛型类,可以通过参数的类型来指定要存储的对象的类型。ThreadLocal 类的声明大致如下:
public class ThreadLocal <T>
{//存储public void set (T value) {...}//获取public T get (){...}...
}
  1. 即通过 ThreadLocal<T> 的 T 指定的类型就是 set 方法的参数的类型以及 get 方法的返回值的类型。

11.5 Thread-Specific Storage模式中的角色

11.5.1 Client(委托者)

  1. Client 角色将处理委托给 TSObjectProxy 角色。一个 TSObjectProxy 角色会被多个 Client 角色使用。

11.5.2 TSObjectProxy(线程特有的对象的代理人)

  1. TSObjectProxy 角色会执行多个Client角色委托给它的处理。
  2. 首先,TSObjectProxy 角色使用 TSObjectCollection 角色获取与 Client 角色对应的TSObject 角色。接着,它将处理委托给TSObject角色。

11.5.3 TSObjectCollection(线程特有的对象的集合)

  1. TSObjectCollection 角色有一张 Client 角色与 TSObject 角色之间的对应表。当 getTSObject()方法被调用后,它会去查看对应表,返回与 Client 角色相对应的 TSObject 角色。另外,当setTSObject()方法被调用后,它会将 Client 角色与 TSObject 角色之间的键值对应关系设置到对应表中。
  2. 在示例程序中,由 Java.lang.ThreadLocal 类扮演此角色。

11.5.4 TSObject(线程特有的对象)

  1. TSObject 角色中保存着线程特有的信息。
  2. TSObject 角色由 TSObjectCollection 角色管理。TSObject角色的方法只会被单线程调用。

11.5.5 类图与时序图

11.6 拓展思路的要点

11.6.1 局部变量与 java.lang.ThreadLocal 类

  1. 线程本来都是有自己特有的存储空间的,即用于保存方法的局部变量的栈。方法中定义的局部变量属于该线程特有,其他线程无法访问它们。但是,这些变量在方法调用结束后就会消失。而 ThreadLocal 则与方法调用无关,它是一个用于为线程分配特有的存储空间的类

11.6.2 保存线程特有的信息的位置

  1. 线程特有的信息的 “保存位置” 有以下两种:

    • 线程外(thread-external)
    • 线程内(thread-internal)

11.6.2.1 在线程外保存线程特有的信息

  1. 示例程序中的线程特有的信息是 TSLog 的实例,而所有的 TSLog 的实例都被保存在 Log 类中的Java.lang.ThreadLocal 的实例中。
  2. ThreadLocal 的实例就是储物间,各个线程的储物柜都被集中在这个储物间内。线程并不会背着储物柜四处走动。像这样,将线程特有的信息保存在线程外部的方法称为 “线程外”。
  3. 将线程特有的信息保存在线程外部的方法不需要修改既有的表示线程的类,所以可以适用于任何线程。但是,随之而来的是表示线程的类的代码可能会变得难以理解。这是因为,仅仅查看表示线程的类的源代码是无法知道其他类中是否还保存着线程特有的信息的。

11.6.2.2 在线程内保存线程特有的信息

  1. 假设我们编写了一个Thread类的子类 MyThread。如果在MyThread中声明字段,该字段就是线程特有的信息。这就是在线程内保存线程特有的信息。采用这种方法时,通过阅读线程的源代码可以很容易地知道线程有哪些特有的信息。但是,随之而来的是当以后需要增加线程特有的信息时,必须修改MyThread类。
  2. 我们使用 “有” 这个词的时候,有时候表示的是 “拥有” 的意思,有时候也表示实际地 “在手上” 的意思。
  3. 例如 “有钱” 这个词并不一定表示钱就确实地 “在手中” 。这是因为,有可能钱被存放在了诸如银行这样的TSObjectCollection角色里面。

11.6.2.3 总结

  1. 在线程外部保存线程特有的信息的方法:虽然有钱,但是钱不在手中
  2. 在线程内部保存线程特有的信息的方法:钱确实地在自己手中

11.6.3 不必担心其他线程访问

  1. Thread-Specific Storage 模式为我们提供了一种以线程作为键,让每个线程只能访问它特有的对象的机制。
  2. 允许被多个线程访问的是 TSObjectProxy 角色。接着,TSObjectProxy角色(使用TSObjectCollection角色)将 TSObject 角色分配给了各个线程。在Thread-Specific Storage模式中,在多个线程之间被共享的部分只到TSObjectProxy角色为止,实际的处理是在将 TSObject 角色分配给每个线程之后才执行的。

11.6.4 吞吐量的提高很大程序上取决于实现方式

  1. Thread-Specific Storage 模式并没有执行互斥处理。因此,这很容易让人误解为与使用Single Threaded Execution模式相比,此时的吞吐量会有所提高。
  2. 但是事实上可能 TSObjectCollection 角色中执行了隐藏的互斥处理。此外,每次通过 TSObjectProxy 角色调用方法时,使用 TSObjectCollection 角色来获取 TSObject 角色都会产生额外的性能开销。
  3. 与强调吞吐量相比,Thread-Specific Storage 模式更看重如下所示的可复用性:
    • 不改变结构即可实现程序
    • 没有显式地执行互斥处理,所以编程时犯错的可能性较小

11.8 基于角色与基于任务

11.8.1 主体与客体

  1. 要想组装塑料模型,以下二者缺一不可:

    • 组装塑料模型的人
    • 塑料模型套件(说明书和零件)

只有组装塑料模型的人或是只有塑料模型套件时,无法完成塑料模型。

  1. 同理,假设我们需要让线程去完成一项工作,那么以下二者缺一不可:

    • 进行工作的线程
    • 进行工作所需的信息
  2. 无论是组装塑料模型,还是让线程进行工作,以下二者缺一不可:

    • 用于做某事的主体
    • 用于做某事的客体
  3. 在设计多线程程序时,根据以 “主体” 为主还是以 “客体” 为主的不同产生了以下两种方式:

    • 基于角色:以主体为主
    • 基于任务:以客体为主

11.8.2 基于角色的考虑方式

  1. 所谓基于角色,一言以蔽之即 “线程最伟大” 的方式。
  2. 基于角色的方式即在表示线程的实例中保存进行工作所必需的信息(上下文、状态)。这样可以减少和减轻线程之间的交互信息量。一个线程会使用从其他线程接收到的信息来执行处理,改变自己的内部状态。通常,我们称这样的线程为角色
  3. 假设我们要编写一段程序,在这段程序中定义了一个Thread类的子类,然后在子类中定义了一个字段,并在这个字段中保存与工作相关的信息。这样,我们就完成了一个 “小角色”:
class Actor extends Thread\
{角色的内部状态public void run (){循环地从外部接收并执行任务,改变内部状态}
}

11.8.3 基于任务的考虑方式

  1. 所谓基于任务,一言以蔽之即 “任务最伟大” 的方式。
  2. 基于任务的方式不在线程中保存信息(上下文、状态)。在这种方式下,这些信息不保存在线程中,而是保存在线程之间交互的实例中。而且,不仅是数据,连用于执行请求的方法都定义在其中。像这样在线程之间交互的实例可以称为消息、请求或是命令。这里我们暂且称其为任务
  3. 由于任务中保存了足够的信息,所以任何线程执行该任务都没有问题。可以说,这是一种富(rich)任务往来于轻线程之间的方式。
  4. 使用该方式的一个典型的模式是Worker Thread模式。
  5. 我们为带有信息的类加上 implements Runnable,然后实现run方法后,线程就可以执行该类了。这样就编写完成了一个 “小任务”。将编写完成的任务传递给线程后,线程就会进行工作:
class Task implements Runnable
{进行工作所必须的信息public void run (){工作的处理内容}
}

第11章-ThreadSpecificStorage相关推荐

  1. 0与1c语言编译,C语言程序设计(07776-1)第11章编译预处理课案.ppt

    C语言程序设计(07776-1)第11章编译预处理课案.ppt 第11章 编译预处理 主要内容 宏定义 文件包含 条件编译 程序案例 小结 习题 11-1 宏定义 不带参数的宏定义 带参数的宏定义 终 ...

  2. 第11章 假如没有编程 《丰富多彩的编程世界》

    第11章 假如没有编程 <丰富多彩的编程世界> 丰富多彩的编程世界 作者 陈光剑 第1章 名可名非常名 第2章 语言的构成 第3章 有趣的编程 第4章 编程语言大观 第5章 编程语言的组成 ...

  3. 《Learning Scrapy》(中文版)第11章 Scrapyd分布式抓取和实时分析

    序言 第1章 Scrapy介绍 第2章 理解HTML和XPath 第3章 爬虫基础 第4章 从Scrapy到移动应用 第5章 快速构建爬虫 第6章 Scrapinghub部署 第7章 配置和管理 第8 ...

  4. 软件开发计划_敏捷软件开发实践:估算与计划读书笔记113第11章 确定渴望度优先级...

    <敏捷软件开发实践:估算与计划>第11章 确定渴望度优先级,重点和要点的思维导图及文字内容. 第11章 确定渴望度优先级 If you have a choice of two thing ...

  5. python编程从入门到实践课后题答案-《Python编程:从入门到实践》课后习题及答案—第11章...

    第11章 测试代码 11-1 城市和国家 :编写一个函数,它接受两个形参:一个城市名和一个国家名.这个函数返回一个格式为City, Country 的字符串,如Santiago, Chile .将这个 ...

  6. python封装类在当前文件中使用_name_下调用不了_学python中对于类怎么也不明白,对了是看到简明教程11章,类与变量的对象....想要通俗易懂的答案....

    代码(简明python教程第11章,感觉看懂了大半但是其中我没调用的为什么也有...谢谢!!!):#coding:utf-8#数据结构好抽象啊..#python的空格制表位,是灾难的开始啊#init制 ...

  7. 【控制】《鲁棒控制-线性矩阵不等式处理方法》-俞立老师-第11章-大系统的分散控制

    第3章 回到目录 第5章 第11章-大系统的分散控制 11.1 时滞系统的分散稳定化控制 11.1 时滞系统的分散稳定化控制

  8. 【控制】《复杂运动体系统的分布式协同控制与优化》-方浩老师-第11章-意图场模型干预下的人机共享控制

    第10章 回到目录 无 第11章-意图场模型干预下的人机共享控制 11.1 引言 11.2 问题描述 11.3 基于意图场的共享控制算法设计 11.3.1 意图场模型设计与分析 11.3.2 共享控制 ...

  9. 【控制】《多智能体系统的协同群集运动控制》陈杰老师-第11章-基于邻居相关状态的多智能体非合作行为检测与隔离

    第10章 回到目录 无 代码地址:https://github.com/Jichao-Zhao/MAS_CooperativeClusterMotionControl 第11章-基于邻居相关状态的多智 ...

  10. 【控制】《多无人机协同控制技术》周伟老师-第11章-多无人机协同航迹规划方法

    第10章 回到目录 第12章 第11章-多无人机协同航迹规划方法 11.1 航迹规划常用算法 11.2 改进动态规划算法的航迹规划 11.2.1 路径节点生成 11.2.2 最短路径生成 11.2.3 ...

最新文章

  1. SQL数据库无法附加 823错误修复 连接中断
  2. 如何生成java_如何生成JavaAPI doc
  3. SPI总线(一):基本原理篇
  4. Shadow Brokers扬言兜售新漏洞攻击工具
  5. Java中Comparator和Comparable之间的区别
  6. 球形坐标和Cartesian 坐标的转换 spherical coordinate
  7. 【跨域问题】Vue简单封装axios—解决post请求后端接收不到参数问题
  8. VUE3.x(v-for)循环遍历指令
  9. 【渝粤教育】国家开放大学2018年春季 4990T电子商务概论(农) 参考试题
  10. iOS底层探索之类的结构—cache分析(上)
  11. Github上如何找开源代码
  12. 大数据笔记--scala(第一篇)
  13. 2048游戏(C语言)
  14. 沉船会有什么_泰坦尼克号为何会沉没,百年来又为何一直没有打捞?专家一声叹息...
  15. 常用电子元器件介绍 齿轮规格的参数
  16. Eclipse启动失败,提示查看.metadata文件夹下的.log文件
  17. UCOSIII的任务管理
  18. Dockerfile 中 CMD 为什么要避免使用 sh -c
  19. Oracle日常性能查看
  20. Alipay(支付宝)接口相关

热门文章

  1. 【光纤专题】单模光纤和多模光纤有哪些不同之处?《建议收藏》
  2. 技术总监面试有什么技巧
  3. 如何刷百度搜索下拉框进行营销引流?
  4. abb机器人指令手册_ABB机器人CCLink 配置
  5. Python检测重复字——部分中华字经重复字检测
  6. 格式化的硬盘能恢复吗 硬盘格式化以后能恢复吗
  7. php公众号上传网络图片_PHP通过CURL上传图片(微信公众号上传素材)
  8. xd使用技巧_Adobe XD —你不知道的30条提示和技巧!
  9. Flutter bottomSheet的使用
  10. Wannacry“永恒之蓝”勒索病毒最全防范措施