1.MDC put

用MDC的put方法,把需要的context添加到当前线程的context map中。

之前说过,子线程在创建的时候会把父线程中的inheritableThreadLocals变量设置到子线程的inheritableThreadLocals中,而MDC内部是用InheritableThreadLocal实现的,所以自然会把父线程中的上下文带到子线程中。

2.getCopyOfContextMap

对于线程池中的线程来说,这部分线程是可以重用的,但是线程本身只会初始化一次,所以之后重用线程的时候,就不会进行初始化操作了,也就不会有上一段中提到的父线程inheritableThreadLocals拷贝到子线程中的过程了。

这个时候如果还想传递父线程的上下文的话,就要使用getCopyOfContextMap方法。

/*** Return a copy of the current thread's context map. Returned value may be* null.*/public Map getCopyOfContextMap() {lastOperation.set(READ_OPERATION);Map<String, String> hashMap = copyOnInheritThreadLocal.get();if (hashMap == null) {return null;} else {return new HashMap<String, String>(hashMap);}}

该方法会把当前线程的context制作一份副本返回。

ExecutorService.execute(new Runnable())的时候,在Runnable构造的时候,用这个方法得到一个Map,保存起来,这时的context是父线程的。

然后在执行run方法的时候,放到MDC中去——子线程的context map中去。

可以自己封装一个AbstractRunnable类,对Runnable的run方法进行一个包装,

public abstract class MdcRunnable implements Runnable {/*** 为了线程池中的线程在复用的时候也能获得父线程的MDC中的信息,* 子线程第一次初始化的时候没事,因为通过InheritableThreadLocal* 已经可以获得MDC中的内容了*/private final Map mdcContext = MDC.getCopyOfContextMap();@Overridepublic final void run() {// 线程重用的时候,把父线程中的context map内容带入当前线程的context map中,// 因为线程已经初始化过了,不会像初始化时那样通过拷贝父线程inheritableThreadLocals到子线程// 的inheritableThreadLocals操作来完成线程间context map的传递。// 真正执行到这个run方法的时候,已经到了子线程中了,所以要在初始化的时候用// MDC.getCopyOfContextMap()来获得父线程contest map,那时候还在父线程域中if (mdcContext != null) {MDC.setContextMap(mdcContext);}try {runWithMdc();} finally {MDC.clear();}}protected abstract void runWithMdc();
}

用户真正需要实现的执行任务的方法是runWithMdc方法。

log(四)——MDC使用相关推荐

  1. log(一)——MDC入门

    1.MDC是什么 先来一段原版注释, /*** This class hides and serves as a substitute for the underlying logging* syst ...

  2. log(二)——MDC实现之ThreadLocal

    因为MDC底层是用ThreadLocal实现的,所以这里补充一些和ThreadLocal相关的知识点. 1.ThreadLocal的三个层次 关于ThreadLocal有三个层次,可以按照这三个层次去 ...

  3. log(五)——MDC总结

    1.为什么最开始子线程会得到父线程MDC设置的内容? 创建子线程的时候会调用init(ThreadGroup g, Runnable target, String name,long stackSiz ...

  4. MySQL——binlog,redo log

    一.什么是binlog.redo log binlog属于逻辑日志,是逻辑操作.innodb redo属于物理日志,是物理变更.逻辑日志有个缺点是难以并行,而物理日志可以比较好的并行操作. binlo ...

  5. 【Caffe】利用log文件绘制loss和accuracy(转载)

    (原文地址:http://blog.csdn.net/liuweizj12/article/details/64920428) 在训练过程中画出accuracy 和loss曲线能够更直观的观察网络训练 ...

  6. Node.js详解(四):连接MongoDB

    文章目录 一.安装MongoDB访问驱动 二.连接数据库 三.添加数据 四.添加多条数据 五.修改数据 六.查询数据 1.查询单条记录 2.查询多条记录 七.删除数据 八.完整示例代码 1.路由 Ap ...

  7. firefox 扩展

    firefox 扩展 <table border="0" cellpadding="4"> <tbody><tr> < ...

  8. 第五课:系统目录及ls·文件类型及alias命令介绍

    1.上过一次我们学习了单用户和救援模式及服务器秘钥登录等操作,而我们最终的目的还是要操作和使用linux系统,所以我们今天先初步学习linux的基本命令如下: 一·目录介绍        ls命令介绍 ...

  9. Oracle 常用运维命令整理

    一.oracle建库与删库命令 (1)oracle11g建库(一般习惯配置gdbname与sid名一样,sys密码与system密码一样,以方便记忆) [oracledb@ ~]$ dbca -sil ...

最新文章

  1. Workbench Could not connect the SSH Tunnel Authentication error
  2. .net获取ip地址
  3. [windows server 2008 站点系列五]一招加速域用戶的文件查找速度
  4. mpls ldp lsp建立过程——Vecloud
  5. 摩尔定律会死亡吗 芯片到底可以变得有多小
  6. 从零开始学计算机组装与维修技术,从新手到高手:电脑组装、维护与故障排除...
  7. php mysql 查询缓存_mysql 查询缓存使用详解
  8. codejam题目_嵌套深度-Google CodeJam 2020资格回合问题解决方案
  9. 信息学奥赛C++语言: 不与最大数相同的数字之和
  10. spark基础之spark streaming的checkpoint机制
  11. 英特尔扶正临时CEO 打破公司50年CEO选拔传统
  12. Python Imaging Library: ImageFile Module(图像文件模块)
  13. VFP基础教程 2.10 计数、求和与求平均值
  14. STARK论文记录(2021CVPR):Learning Spatio-Temporal Transformer for Visual Tracking
  15. 阿阿斯顿发沙发是地方撒旦法
  16. manster网易云音乐大数据分析
  17. Markdown教程--Markdown图片
  18. 【Python】python数据库编程
  19. GO语言gin框架实战-02-Jwt和登录认证
  20. Android Audio - 支持多应用同时录音_Android9.0修改方法

热门文章

  1. 使用Python提取Excel中单元格中的某一段内容(包含某特定字符且前后以逗号作为分隔符的内容)
  2. Visual C++ 2010如何解决程序运行闪退问题
  3. 考研还是工作?回过头来反思我当初为何没考研
  4. python全栈学习--day45(前端HTML)
  5. 【Cadence使用】PCB元器件匹配3D模型
  6. 统计出各分数段的人数
  7. 商品3D展示来啦,HMS Core3D建模服务助力电商发展
  8. Ubuntu 20.04 物理机安装
  9. 吐血分享:QQ群霸屏技术教程(接单篇)
  10. 二、小兔仙Vue3(项目介绍)