📖 本章预览
本章为预览版本,展示部分核心内容。完整内容包含详细源码解析、实战代码和面试要点,加入知识星球即可解锁全部章节。
第六章:线程池一跑 traceId 就丢了怎么破 — TaskWrapper 装饰器链
本章目标:理解 TaskWrapper 如何用装饰器模式解决跨线程上下文丢失问题,掌握 DtpRunnable 双引用设计的精妙之处,学会自定义 TaskWrapper 扩展。
6.1 问题复现
在 Web 应用中,框架会在当前线程的 MDC 中放入 traceId,方便全链路日志追踪。但当你把任务丢给线程池执行时:
// 主线程:MDC 中有 traceId = "abc123"
executor.execute(() -> {
log.info("处理订单"); // ← 这里 MDC 是空的,traceId 丢了!
});
线程池的工作线程和提交线程不是同一个线程,MDC 基于 ThreadLocal,数据不会自动传递。同样的问题也出现在 TransmittableThreadLocal、SecurityContext 等场景。
DynamicTP 的解决方案:在任务提交前,用装饰器链对 Runnable 层层包装,把上下文"捎带"进去。
6.2 TaskWrapper 极简接口
@FunctionalInterface
public interface TaskWrapper {
/**
* 包装器名称,用于配置文件中按名称选择
*/
default String name() {
return null;
}
/**
* 核心方法:接收原始 Runnable,返回增强后的 Runnable
*/
Runnable wrap(Runnable runnable);
}
设计精妙之处:
@FunctionalInterface标注,只有一个抽象方法wrap(),可以用 Lambda 实现- 输入一个 Runnable,输出一个 Runnable — 标准的装饰器模式签名
- 它不关心你要传递什么上下文,只要求你把"传递逻辑"封装成
Runnable → Runnable的变换
6.3 装饰器链执行
包装不是一次完成的,而是链式执行。核心逻辑在 TaskEnhanceAware 接口中:
public interface TaskEnhanceAware extends DtpAware {
default Runnable getEnhancedTask(Runnable command,
List<TaskWrapper> taskWrappers) {
// 1. 保存原始 Runnable 的引用
Runnable wrapRunnable = command;
// 2. 如果任务实现了 NamedRunnable,提取任务名称
String taskName = (wrapRunnable instanceof NamedRunnable)
? ((NamedRunnable) wrapRunnable).getName()
: null;
// 3. 装饰器链:按顺序逐个包装
if (CollectionUtils.isNotEmpty(taskWrappers)) {
for (TaskWrapper t : taskWrappers) {
wrapRunnable = t.wrap(wrapRunnable);
}
}
// 4. 最终封装为 DtpRunnable
return new DtpRunnable(command, wrapRunnable, taskName);
}
}
假设配置了 ["ttl", "mdc"],执行流程如下:
原始 Runnable (command)
│
├── TtlTaskWrapper.wrap() → TtlRunnable(捕获 TTL 快照)
│
├── MdcTaskWrapper.wrap() → MdcRunnable(捕获 MDC 快照)
│
└── new DtpRunnable(原始command, 最终wrapRunnable, taskName)
包装顺序由 taskWrappers 列表的顺序决定,最后包装的最先执行(洋葱模型)。
6.4 DtpRunnable 双引用设计
@Getter
public class DtpRunnable implements Runnable {
private final Runnable originRunnable; // 原始任务(未经任何包装)
private final Runnable runnable; // 包装后的任务(实际执行)
private final String taskName; // 任务名称
🔒 解锁完整内容
本章剩余内容需要解锁后查看
以上仅为本章部分预览内容,完整内容包含更多深度源码解析、实战代码和面试要点。
加入知识星球你将获得:
- ✅ 全部 12 章完整内容 + 持续更新
- ✅ 配套源码 + 实战项目
- ✅ 一对一答疑 + 面试辅导
- ✅ 简历优化 + 内推机会
📚 本章完整目录
以下为本章完整目录结构,加入知识星球即可解锁全部内容。