log(四)——MDC使用
?1.MDC put
用MDC的put方法,把需要的context添加到當(dāng)前線程的context map中。
之前說過,子線程在創(chuàng)建的時(shí)候會把父線程中的inheritableThreadLocals變量設(shè)置到子線程的inheritableThreadLocals中,而MDC內(nèi)部是用InheritableThreadLocal實(shí)現(xiàn)的,所以自然會把父線程中的上下文帶到子線程中。
2.getCopyOfContextMap
對于線程池中的線程來說,這部分線程是可以重用的,但是線程本身只會初始化一次,所以之后重用線程的時(shí)候,就不會進(jìn)行初始化操作了,也就不會有上一段中提到的父線程inheritableThreadLocals拷貝到子線程中的過程了。
這個(gè)時(shí)候如果還想傳遞父線程的上下文的話,就要使用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);}}該方法會把當(dāng)前線程的context制作一份副本返回。
ExecutorService.execute(new Runnable())的時(shí)候,在Runnable構(gòu)造的時(shí)候,用這個(gè)方法得到一個(gè)Map,保存起來,這時(shí)的context是父線程的。
然后在執(zhí)行run方法的時(shí)候,放到MDC中去——子線程的context map中去。
可以自己封裝一個(gè)AbstractRunnable類,對Runnable的run方法進(jìn)行一個(gè)包裝,
public abstract class MdcRunnable implements Runnable {/*** 為了線程池中的線程在復(fù)用的時(shí)候也能獲得父線程的MDC中的信息,* 子線程第一次初始化的時(shí)候沒事,因?yàn)橥ㄟ^InheritableThreadLocal* 已經(jīng)可以獲得MDC中的內(nèi)容了*/private final Map mdcContext = MDC.getCopyOfContextMap();@Overridepublic final void run() {// 線程重用的時(shí)候,把父線程中的context map內(nèi)容帶入當(dāng)前線程的context map中,// 因?yàn)榫€程已經(jīng)初始化過了,不會像初始化時(shí)那樣通過拷貝父線程inheritableThreadLocals到子線程// 的inheritableThreadLocals操作來完成線程間context map的傳遞。// 真正執(zhí)行到這個(gè)run方法的時(shí)候,已經(jīng)到了子線程中了,所以要在初始化的時(shí)候用// MDC.getCopyOfContextMap()來獲得父線程contest map,那時(shí)候還在父線程域中if (mdcContext != null) {MDC.setContextMap(mdcContext);}try {runWithMdc();} finally {MDC.clear();}}protected abstract void runWithMdc(); }
?
用戶真正需要實(shí)現(xiàn)的執(zhí)行任務(wù)的方法是runWithMdc方法。
總結(jié)
以上是生活随笔為你收集整理的log(四)——MDC使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pear安装
- 下一篇: 2022R2移动式压力容器充装考题模拟考