ThreadLocal (三):为何TransmittableThreadLocal
2024-10-21 09:13:46
一、示例
线程池内的线程并没有父子关系,所以不适合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() {
@Override
public void run() {
ThreadPoolInheritableThreadLocalDemo.threadLocal.set("superWorld"+j); ThreadPoolInheritableThreadLocalDemo.pool.execute(new Runnable() {
@Override
public 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对象
*/
@Override
public 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<?>, ?>>() {
@Override
protected Map<TransmittableThreadLocal<?>, ?> initialValue() {
return new WeakHashMap<TransmittableThreadLocal<?>, Object>();
} @Override
protected 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
@Override
public 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);
}
}
参考:
最新文章
- VI的一些快捷键
- strncpy和memcpy的区别
- POJ3041Asteroids(二分图最少顶点覆盖)
- Spring REST实践之Spring Boot
- transform的2D部分,嗯…就这个标题了。
- Salesforce开发者学习笔记之二:Salesforce开发平台应用场景
- filebeat.yml(中文配置详解)
- 剑指Offer-链表中环的入口结点
- UI设计切忌墨守成规,但改变也须用数据说话
- lenovo 笔记本ideapad 320c-15改装win7问题
- abaqus的umat在vs中debug调试
- c# base64编码解码
- windows 7 下用git
- Editplus中添加System.out.println()快捷键
- eclipse Git配置
- 欢迎来怼--第三十七次Scrum会议
- 05慕课网《进击Node.js基础(一)》HTTP概念进阶(同步/异步)
- Java_多线程2_线程池
- linux系统中python版本升级
- 微信小程序(2)——新建页面
热门文章
- RabbitMQ Performance Testing Tool 性能测试工具
- Atitit.&#160;Async&#160;await&#160;优缺点&#160;异步编程的原理and实现&#160;java&#160;c#&#160;php
- Camera2/HAL3
- 基于Python3 + OpenCV3.3.1的远程监控程序
- sigaction()之sa_mask
- Visual Studio 调试小技巧-从查看窗口得到更多信息(转)
- redhat5.8系统学习
- 使用nmap 验证多种漏洞
- html+css+JavaScript贪吃蛇
- 小米Note全网通支持7模19频:先发标准版