ThreadLocal物件使用過程中容易陷入的坑

2021-09-07 15:53:42 字數 1021 閱讀 7161

今天碰到的坑是這樣的:

其中a請求會經過interceptor01***,interceptor01內部會將a請求傳遞的module_name引數存入本地執行緒變數,b請求不會經過***,c請求會經過***,但是不會傳遞module_name,這時執行緒變數會存入乙個空的module_name。

因此懷疑是不是module_name引數沒有存入本地執行緒,經過幾番查詢發現,b請求不經過***,所以b請求中拿不到module_name是正常的,但是奇怪的是,b請求竟然能夠拿到本地執行緒變數中的其它的屬性值,真實百思不得其解,因為可以確定,執行緒變數只有在***interceptor01中才會初始化並賦值!

讓我們再梳理一下,b請求沒有經過***,那麼本地執行緒變數就沒有初始化,但是在b請求中取本地執行緒變數的時候,竟然能取到,只是唯獨module_name取不到。

好吧,可以肯定執行緒變數只能在本執行緒中獲取到,那麼只有乙個解釋,那就是b請求與別的請求共用了同乙個執行緒!換句話說,並不是每乙個請求,web容器都會使用不同的執行緒來處理。為了證實這一想法,我將a、b、c請求的threadid列印出來比對,發現果然是一樣的。

這就可以解釋上述的問題了:

當我們第一次進入index01.html頁面,a請求會經過***,然後初始化執行緒變數,存入module_name;

接著b請求不會經過***,但是由於和a請求使用的是同乙個執行緒,所以能夠正常取出module_name,並成功上傳;

接著c請求會經過***,但是不會傳遞module_name,所以把執行緒中的module_name就置空了;

最後當我們再次上傳傳送b請求的時候,執行緒中就沒有module_name了。

下面說說為什麼3個請求會共用乙個執行緒,2個原因:

1、http1.1協議中的keep-alive是預設開啟的,同乙個會話中,有限的請求是共用乙個長連線的。

2、tomcat預設使用執行緒池,所以乙個執行緒的生命週期不能對等於乙個請求的生命週期,執行緒池中的執行緒是可以被復用的。

解決方案:

1、保證每次都用新的值覆蓋執行緒變數;

2、保證在每個請求結束後清空執行緒變數。

ThreadLocal使用介紹

首先有幾點需要大家清楚的 1 threadlocal 只是對需要儲存的物件的管理,而儲存實際是由當前thread 負責。個人理解為threadlocal 是乙個操作thread.threadlocals 的工具。2 使用threadlocal 可以使物件達到執行緒隔離的目的。同乙個threadloc...

ThreadLocal使用案例

本文藉由併發環境下使用執行緒不安全的 dateformat優化案例,幫助大家理解threadlocal.public class dateutil catch parseexception e 首先分析下 該處的函式parseymdhms 使用了synchronized修飾,意味著該操作是執行緒不安...

非同步執行緒threadLocal中物件獲取失敗

問題描述 在乙個比較複雜的業務中,同步執行了主任務,將與當前任務無關的任務丟進了非同步執行緒,然後發現非同步執行緒沒有獲取到使用者。所有的非同步任務都沒有執行下去。排查1.直接debug,發現任務在非同步方法開始執行就失敗了,沒有進入非同步方法 2.打log,非同步方法前的log列印了,之後的沒有。...