1.为什么最开始子线程会得到父线程MDC设置的内容?
创建子线程的时候会调用init(ThreadGroup g, Runnable target, String name,long stackSize)方法,判断如果parent.inheritableThreadLocals不为null就调用createInheritedMap方法把父线程的ThreadLocal里保存的变量都加载到子线程的ThreadLocal中去。所以MDC类的静态变量mdcAdapter(LogbackMDCAdapter实现)中的copyOnInheritThreadLocal会得到父类MDC写入的内容,因为它用的是InheritableThreadLocal这个继承类。
2.如果用的是ThreadLocal就做不到了吗?
是的,InheritableThreadLocal覆写的getMap和createMap方法才会操作到inheritableThreadLocals这个变量。
3.如果不用MDC.clear()的话会有什么影响?
答:如果都是用new Thread方法建立的线程没有问题,因为之后线程会消亡。
但是如果用ThreadPool线程池的话,线程是可以重用的,如果之前的线程的MDC内容没有清除掉的话,再次重线程池中获取到这个线程,会取出之前的数据(脏数据),会导致一些不可预期的错误,所以当前线程结束后一定要清掉。可以用上一篇提到的的AbstractRunnable这个类,封装了clear操作,程序员只需关心业务即可,不要担心忘记clear了。