ThreadLocal Thread Pool Multithreading Multi Threaded

在Multithreading的專案中,使用ThreadLocal儲存各自的變數

陳膺傑 2016/12/12 14:44:13
1922







主題

Multithreading的專案中,使用ThreadLocal儲存各自的變數

文章簡介

介紹在multithreading的情況下,如何使用全域變數(global variable),彼此的內容又不會互相影響並且注意到,透過這樣的解決方案,是否可能導致其他問題產生!

作者

陳膺傑

版本/產出日期

V1.0/2016.12.08




1. 前言

在開發Web Services時,若可能遇到多人同時呼叫,透過Multi Thread進行處理時,在使用全域變數(global variable)上,就得特別小心可能存在值被覆蓋的問題。






2. 目的

為解決Multi Thread下使用全域變數(global variable),內容會互相覆蓋的問題,可透過ThreadLocal來存放專屬於當前Thread的全域變數(global variable)。

當ThreadLocal遇上Thread Pool時,可能產生嚴重的問題!必須先了解並預防!






3. 使用ThreadLocal

從JDK5.0開始,ThreadLocal已支援泛型,透過set存入value,透過get取得value。






4. ThreadLocal範例演練

4.1、 建立一個RESTfulWeb Service,當接到的內容不為空即存入ThreadLocal,接著呼叫另一個method來取得ThreadLocal的內容,回傳內容。



4.2、 同時呼叫此Web Service時,彼此結果並不會互相影響。

圖一:輸入「Jay Chen」,成功取得「Jay Chen」


圖二:輸入「Adam」,成功取得「Adam」。





5. ThreadLocal遇上Thread Pool

5.1、 當上述的範例,不輸入內容再次同時呼叫

圖一:Thread-1仍然取得「Jay Chen」


圖二:Thread-2仍然取得「Adam」



5.2、 會發生此錯亂,全是因為Thread Pool的影響,Thread受到Thread Pool的管理,在處理流程結束後,回到Thread Pool等著處理下一筆request,為了效能,通常這些Threads並不會一直重新產生,而是重複利用,所以當我們使用ThreadLocal存放變數時,若是沒有任何初始或清除的動作,將會被下一個使用者取到上一個使用者的內容。






6. 解決辦法

6.1、 新增清除的method


6.2、 在結束流程後,清除ThreadLocal,原本的Web Service調整如下


6.3、 再次進行測試

圖一:輸入「BoB」,在Thread-2成功取得BoB


圖二:不輸入內容,在Thread-2取不到內容



7. 結論

現行大多數的Server都會透過Thread Pool來管理Threads,因此在使用ThreadLocal上,需要特別注意,在流程處理結束後,必須清除所有存放的ThreadLocal,以確保不會造成這種資料錯亂的情況,更嚴重的情況還可能導致Memory leak!


8. 參考來源

Java ThreadLocal-http://tutorials.jenkov.com/java-concurrency/threadlocal.html

ThreadLocal Variables and Thread Pools – It Can Go Wrong-https://techblog.bozho.net/threadlocal-variables-and-thread-pools-it-can-go-wrong/

A Painless Introduction to Java’s ThreadLocal Storage-https://www.appneta.com/blog/introduction-to-javas-threadlocal-storage/

Ensure ThreadLocal variables are reinitialized when using thread pools-https://www.securecoding.cert.org/confluence/display/java/TPS04-J.+Ensure+ThreadLocal+variables+are+reinitialized+when+using+thread+pools

陳膺傑