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