log4j中的%x ---NDC,%X---MDC

即%x 

NDC.clear();
NDC.push(this.toString());
%X{first} %X{last}
MDC.put("first", "Dorothy"); Logger logger = LoggerFactory.getLogger(SimpleMDC.class); // We now put the last name MDC.put("last", "Parker");

mdc 实际上是一个封装了ThreadLocal变量的一个类。

官方实现:mdc 包含了一个ThreadLocalMap   因为  ThreadLocalMap extends InheritableThreadLocal  所以他有特性1:可以向下传递,2.本身处理的是hashTable 。

  final static MDC mdc = new MDC();
  
  static final int HT_SIZE = 7;

  boolean java1;
  
  Object tlm;

  private Method removeMethod;

  private
  MDC() {
    java1 = Loader.isJava1();
    if(!java1) {
      tlm = new ThreadLocalMap();
    }

    try {
      removeMethod = ThreadLocal.class.getMethod("remove", null);
    } catch (NoSuchMethodException e) {
      // don't do anything - java prior 1.5
    }
  }

NDC

一层一层深入 发现也是包含了一个 ThreadLocal,由于它不具有InheritableThreadLocal 的特性,所以开启新线程的时候,需要手动重新设置。

public static void push(String message) {
        ThreadContext.push(message);
    }
    public void push(String message) {
        if (this.useStack) {
            this.add(message);
        }
    }
    public boolean add(String s) {
        if (!this.useStack) {
            return false;
        } else {
            MutableThreadContextStack copy = this.getNonNullStackCopy();
            copy.add(s);
            copy.freeze();
            stack.set(copy);
            return true;
        }
    }
public class DefaultThreadContextStack implements ThreadContextStack {
    private static final long serialVersionUID = 5050501L;
    private static final ThreadLocal<MutableThreadContextStack> stack = new ThreadLocal();
    private final boolean useStack;

开启线程时操作

        final String s=NDC.get();
        final Map<String, String> mdcdata = MDCUtil.peekMap();
        ThreadPoolUtil.ex.execute(new Runnable() {
            @Override
            public void run() {
                MDCUtil.set(mdcdata);
                NDC.push(s);
                alarmInfoSao.sendAlarmEventMsg(alarmEventDTO);
            }
        });