Hystrix系列之ThreadLocal跨線程傳遞問題

在Hystrix系列之前的文章中提到過,如果使用線程池模式,那么存在一個ThreadLocal變量跨線程傳遞的問題,即在主線程的ThreadLocal變量,無法在線程池中使用,不過Hystrix內部提供了解決方案,但是個人覺得這個方案不是那么友好。

解決方案

在Hystrix中,如果想在跨線程時共享數據,必須通過HystrixRequestVariableDefault申明變量

HystrixRequestVariableDefault name = new HystrixRequestVariableDefault();
name.set("占小狼");

其實在用法上,和ThreadLocal是一樣的,只是需要對現有代碼的大量改造。

看下這個方案的實現原理,先從set開始。

public void set(T value) {
  HystrixRequestContext.getContextForCurrentThread().state.put(this, new LazyInitializer<T>(this, value));
}

Hystrix內部通過HystrixRequestContext實現數據的跨線程傳遞,getContextForCurrentThread得到的是當前線程的HystrixRequestContext對象,每個HystrixRequestContext對象都有一個對應ConcurrentHashMap變量state,負責保存通過HystrixRequestVariableDefault初始化的數據。

通過set方法,該對象和數據會被保存在一個當前線程所屬的map中。為了實現數據的跨線程傳遞,只需要在初始化task的時候,把主線程的HystrixRequestContext變量保存起來,在task執行的時候,重新賦值到子線程的上下文中,這樣在子線程中就可以順利拿到這些數據。

Hystrix中通過HystrixContextCallable包裝原始Callable,并使用parentThreadState保存了當前線程的HystrixRequestContext變量。

任務執行時,先保存子線程現有的HystrixRequestContext變量,再賦值主線程的HystrixRequestContext變量,任務執行完成后,重新還原子線程。

如果不想使用Hystrix這種方式實現,也可以使用Hystrix提供的插件方式重新包裝task,通過實現HystrixConcurrencyStrategy類,重寫wrapCallable方法,和Hystrix的實現原理類似。

比如提供一個繼承ThreadLocalXXXThreadLocal類,那么業務方在使用時,就可以這樣使用。

ThreadLocal name = new XXXThreadLocal();
name.set("占小狼");

這種方式看起來對已有邏輯只有一點小小的改動,對于新接入的也不那么陌生。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,869評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,090評論 25 708
  • 人與人之間,如果能夠非暴力溝通,就能減少矛盾、沖突和爭執,從而與他人和諧相處,獲得良好的人際關系。這里給大家...
    十里晴晝閱讀 398評論 3 14
  • 一、從何而來 易澤考研,是易澤教育旗下針對考研領域的教育服務項目。團隊創始人分別來自于清華大學、北京大學、南開大學...
    優研優選閱讀 331評論 0 0
  • 過去的童年不是那么好所以現在不管怎樣都不會說不好 過了好多好多的不是日子的日子想想都覺得害怕 我真的很佩服自己是那...
    統有你知足閱讀 214評論 0 0