ThreadLocal父子線程數(shù)據(jù)傳遞解決方案

前言

在閱讀前,您需要對ThreadLocal用法有一定了解。如果不了解,請參考ThreadLocal用法相關(guān)文章。

子線程如何獲取主線程的ThreadLocal里的數(shù)據(jù)呢?

這個需求或許也很常見,最開始,我們可能會想到InheritableThreadLocal,這是由Jdk為我們提供,他是ThreadLocal的子類,使用方法和ThreadLocal完全相同。

但是這里有幾個坑:
1、手動通過線程池創(chuàng)建線程可能會造成get值為null。
2、項目中我們往往會使用線程池,如果主線程使用的是緩存線程池(比如SpringMvc),線程會復(fù)用,當(dāng)線程執(zhí)行完畢后本次操作后,再次執(zhí)行新的任務(wù)時候,ThreadLocal內(nèi)部數(shù)據(jù)并沒有被清除。
3、ThreadLocal父子線程之間數(shù)據(jù)拷貝默認(rèn)是淺拷貝,這也就意味如果我們多個線程可能會引用同一個內(nèi)存地址,造成多個線程訪問一個對象,輕者會造成線程不安全,重者甚至?xí)hreadLocal數(shù)據(jù)被修改成非預(yù)期結(jié)果。

終級解決方案

這些坑本人親身體驗過,血的教訓(xùn)總結(jié)出來,那么如何很好的解決這些問題呢?這邊給出一個終級解決方案,使用阿里Transmittable ThreadLocal,可以很好的解決上面這些問題。

具體使用方法可以參見文檔:https://github.com/alibaba/transmittable-thread-local

如果使用后發(fā)現(xiàn)在緩存線程池下仍然會出現(xiàn)ThreadLocal沒有被清理干凈的問題,可可嘗試重寫TransmittableThreadLocal afterExecute方法,在此方法中清除線程數(shù)據(jù)。

那么通過阿里的TransmittableThreadLocal 如何解決淺拷貝問題呢?這里它提供了一個copy方法,TransmittableThreadLocal 在進行對象拷貝的時候會調(diào)用copy方法,我們只需要重寫這個方法,讓他變量深復(fù)制即可。

最后,建議大家不要輕意使用ThreadLocal,能不用盡量不要去使用,一旦在緩存線程池下如果數(shù)據(jù)沒有清理干凈會很麻煩,不方便問題排查,而且ThreadLocal有一定情況下會有造成內(nèi)存泄露的風(fēng)險,一定要慎用!慎用!慎用!但并不意味著禁用!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容