log(四)——MDC使用

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();

    @Override
    public 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方法。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ThreadLocal是一种用于存储线程本地变量的机制。它可以让每个线程都拥有自己的变量副本,使得线程之间的变量互不干扰。MDC(Mapped Diagnostic Context)是基于ThreadLocal实现的一种日志跟踪机制。MDC可以在多线程环境下为每个线程记录不同的上下文信息,比如线程名称、请求ID等。 MDC的底层使用的是ThreadLocal来存储数据,但会做一些安全校验。而且MDC还支持子线程继承父线程的thread-local值,即InheritableThreadLocal。 在MDC的源码中,使用了static MDCAdapter mdcAdapter来实际承载数据。这是一个静态类,在整个JVM中只有一份。所以,当我们调用MDC.put时,实际上是将数据存储到mdcAdapter中。 总结来说,ThreadLocal是一种存储线程本地变量的机制,而MDC则是利用ThreadLocal实现的一种日志跟踪机制。MDC可以为每个线程记录不同的上下文信息,使得日志记录更加准确和可靠。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [ThreadLocal&MDC内存泄漏问题](https://blog.csdn.net/xiexiaojing/article/details/122150793)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [MDC、ThreadLocal、InheritableThreadLocal的区别和联系](https://blog.csdn.net/qq_33247435/article/details/127793733)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值