一、示例

线程池内的线程并没有父子关系,所以不适合InheritableThreadLocal的使用场景

public class ThreadPoolInheritableThreadLocalDemo {//    static ThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
//    static ExecutorService pool = Executors.newFixedThreadPool(2);static TransmittableThreadLocal<String> threadLocal = new TransmittableThreadLocal<>();static ExecutorService pool =  TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(3));public static void main(String[] args) {for(int i=0;i<100;i++) {int j = i;pool.execute(new Thread(new Runnable() {@Overridepublic void run() {ThreadPoolInheritableThreadLocalDemo.threadLocal.set("superWorld"+j);ThreadPoolInheritableThreadLocalDemo.pool.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()  +" : " +ThreadPoolInheritableThreadLocalDemo.threadLocal.get());}});
                }}));}}}

二、TransmittableThreadLocal实现分析

读取线程间传递的ThreadLocal 值比较麻烦,ThreadLocal 和 InheritableThreadLocal 都没有开放内部的 ThreadLocalMap,不能直接读取。

所以要么自己完全实现一套 ThreadLocalMap 机制(如 Netty 的 FastThreadLocal),要么就是自己实现 ThreadLocal 的子类,在每次调用 ThreadLocal

的 set/get/remove 等接口的时候,为 Thread 记录到底绑定了哪些需要发生线程间传递的 ThreadLocal 对象。

/***实际存储值的工作还是父类ThreadLocal完成*TransmittableThreadLocal 只是记录了哪些线程使用了TransmittableThreadLocal对象*/@Overridepublic final void set(T value) {super.set(value);if (null == value) { // may set null to remove value
            removeValue();} else {addValue();}}/***holder 只是为了记录使用了哪些 TransmittableThreadLocal 对象*在构造TtlRunnable/TtlCallable 的时候, 通过holder取得对应的TransmittableThreadLocal   *InheritableThreadLocal的默认值是WeakHashMap*/private static InheritableThreadLocal<Map<TransmittableThreadLocal<?>, ?>> holder =new InheritableThreadLocal<Map<TransmittableThreadLocal<?>, ?>>() {@Overrideprotected Map<TransmittableThreadLocal<?>, ?> initialValue() {return new WeakHashMap<TransmittableThreadLocal<?>, Object>();}@Overrideprotected Map<TransmittableThreadLocal<?>, ?> childValue(Map<TransmittableThreadLocal<?>, ?> parentValue) {return new WeakHashMap<TransmittableThreadLocal<?>, Object>(parentValue);}};private void addValue() {if (!holder.get().containsKey(this)) {holder.get().put(this, null); // WeakHashMap supports null value.
        }}private void removeValue() {holder.get().remove(this);}

调用ThreadPoolInheritableThreadLocalDemo.threadLocal.set("superWorld"+j)时,

holder.get().containskey(this) 为false

2. TtlRunnable

构造TtlRunable时,设置线程对应的Map<TransmittableThreadLocal<?>, Object>>

    private TtlRunnable(Runnable runnable, boolean releaseTtlValueReferenceAfterRun) {     //this.copiedRef = new AtomicReference<Map<TransmittableThreadLocal<?>, Object>>(TransmittableThreadLocal.copy());this.runnable = runnable;this.releaseTtlValueReferenceAfterRun = releaseTtlValueReferenceAfterRun;}
TransmittableThreadLocal.copy
    static Map<TransmittableThreadLocal<?>, Object> copy() {Map<TransmittableThreadLocal<?>, Object> copy = new HashMap<TransmittableThreadLocal<?>, Object>();for (TransmittableThreadLocal<?> threadLocal : holder.get().keySet()) {copy.put(threadLocal, threadLocal.copyValue());}return copy;}

3.运行时,备份和恢复Map<TransmittableThreadLocal<?>, Object>

TtlRunnable#run

    @Overridepublic void run() {Map<TransmittableThreadLocal<?>, Object> copied = copiedRef.get();if (copied == null || releaseTtlValueReferenceAfterRun && !copiedRef.compareAndSet(copied, null)) {throw new IllegalStateException("TTL value reference is released after run!");}Map<TransmittableThreadLocal<?>, Object> backup = TransmittableThreadLocal.backupAndSetToCopied(copied);try {runnable.run();} finally {TransmittableThreadLocal.restoreBackup(backup);}}

参考:

transmittableThreadLocal

何为TransmittableThreadLocal相关推荐

  1. 稀疏性如何为AI推理增加难度

    稀疏性如何为AI推理增加难度 NVIDIA Ampere架构使数学运算加倍,以加速对各种神经网络的处理. 如果曾经玩过游戏Jenga,那么将有一些AI稀疏感. 玩家将木制积木交叉成一列.然后,每个玩家 ...

  2. 腾讯联姻开心网意欲何为

    今天杨长升在新浪科技上看到这样一条信息"腾讯日前已收购开心网部分股份,有意成为开心网大股东."据了解,早在8月就曾有消息称,腾讯已收购开心网部分股份,现有一位投资界人士处证实了最新 ...

  3. 如何为ccflow工作流引擎增加一个优先级PRI?

    为什么80%的码农都做不了架构师?>>>    如何为ccflow工作流引擎增加一个优先级PRI? 对于一条流程的优先级可分为 低,中,高三个级别,用这个状态来标示这条流程的紧急程度 ...

  4. ios单应用模式_如何为iOS 13暗模式设置应用

    ios单应用模式 Apple launched the much-awaited iOS 13 updates globally on September 19 across all iPhones ...

  5. jupyter笔记本_如何为Jupyter笔记本电脑设置PySpark

    jupyter笔记本 by Tirthajyoti Sarkar 由Tirthajyoti Sarkar 如何为Jupyter笔记本电脑设置PySpark (How to set up PySpark ...

  6. 如何为Android上的产品设计一款合适的图标

    如 果你已经完成了你的app,你一定会马上向其它人宣布这件事情.但是你需要注意一个很重要的问题,那就是app的图标.你的图标可能在项目启动之 前就已经设计好了,但我不喜欢这样,如果app没有完成实际上 ...

  7. 详解JVM内存管理与垃圾回收机制2 - 何为垃圾

    随着编程语言的发展,GC的功能不断增强,性能也不断提高,作为语言背后的无名英雄,GC离我们的工作似乎越来越远.作为Java程序员,对这一点也许会有更深的体会,我们不需要了解太多与GC相关的知识,就能很 ...

  8. 如何为WPF添加Main()函数

    一般的.WPF的Main()函数是自动生成的,不过有时候我们需要为我们的应用程序传参.那么自动生成的Main()函数就不会满足我们的要求. 那么如何为WPF Application 设置Main()函 ...

  9. 如何为 Flask Web 应用配置 Nginx

    原文地址:How to Configure NGINX for a Flask Web Application 原文作者:patricksoftware 译文出自:掘金翻译计划 本文永久链接:gith ...

最新文章

  1. 如何在浏览器端爬取信息(只是配置的部分)----设置环境
  2. POJ2391 Floyd+离散化+二分+DINIC
  3. hdu 4891 模拟
  4. Python列表中字符串转数字的方法
  5. python中如何输出中文_python中怎么输出中文-问答-阿里云开发者社区-阿里云
  6. 验证码颜色、字母、数字、线条、圆点、位置都随机,点击切换验证码
  7. 利用Karma、Jasmine 做前端单元测试
  8. Pytorch下使用多GPU训练模型
  9. Java后端开发框架
  10. access 分组序号,使用Access SQL进行分组排名
  11. 台式电脑计算机怎么打不开怎么回事,为什么电脑自带的软件打不开怎么办
  12. 11g中hanganalyze的格式
  13. 深圳大学计算机网络实验五:Socket编程
  14. html中index函数,INDEX函数.doc
  15. 1943中途岛海战2020年8月22日海龟画图版(原雷电模拟升级版)
  16. CSDN如何快速提升等级
  17. sql查询今天,近七天,近一个月,近一年的数量统计
  18. 推送服务升级,支持小米推送国际版以及更灵活的推送方式|11月更新
  19. Netty通过Nginx配置 wss 协议访问(实践可行)
  20. SRPG游戏开发(二十三)第七章 寻路与地图对象 - 一 A*寻路算法(A* Search Algorithm)

热门文章

  1. OpenStack(二)——Keystone组件
  2. 如何升级浏览器_Chrome谷歌浏览器秒变科研神器,让你的效率提升10倍!
  3. java构造器调用构造器_java中构造器内部调用构造器实例详解
  4. python科学计数法输出_python不以科学计数法输出的实例方法总结
  5. 限制服务器访问指定网站,如何允许或限制某一国或地区的用户访问网站
  6. ida导入jni头文件_IDA导入Jni.h
  7. 使用了未赋值的局部变量_macOS上的汇编入门(七)——字面量与局部变量
  8. 从java里调用r jri的设置方法_从Java里调用R – JRI的设置方法
  9. 日志框架 android,深度剖析Android JDK 日志框架
  10. (11) nginx + keepalived 双机热备