您好,登錄后才能下訂單哦!
這篇文章給大家介紹ThreadLocal不調用remove方法會導致業務邏輯錯誤的示例分析,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
為什么會導致業務邏輯出錯:
當ThreadLocal用于線程池、web應用或者線程被多次重復使用的時候,特別要注意,以web應用為例:
我們都知道web應用很多類都是單例模式,如spring默認注入方式所創建的類就是一個單例,當不同的http請求到達服務器的時候,實際上都是使用了同一個實例,假如該實例使用了全局變量,當請求A修改了這個變量,后面到來的其它請求(此時不管A請求是否結束),如請求B再使用該變量的時候,實際上是被請求A修改過的,這會導致業務邏輯出錯,而且很難被發現,這種情況,通常是使用ThreadLocal來解決,因為不同的請求雖然使用了同一個實例,但所使用的線程卻不同,但有一點需要特別注意,那就是web容器的線程是重復使用的,web容器使用了線程池,當一個請求使用完某個線程,該線程會放回線程池被其它請求使用,這就導致一個問題,不同的請求還是有可能會使用到同一個線程(只要請求數量大于線程數量),而ThreadLocal是屬于線程的,如果我們使用完ThreadLocal對象而沒有手動刪掉,那么后面的請求就有機會使用到被使用過的ThreadLocal對象,如果一個請求在使用ThreadLocal的時候,是先get()來判斷然后再set(),那就會有問題,因為get到的是別的請求set的內容,如果一個請求每次使用ThreadLocal,都是先set再get,那就不會有問題,因為一個線程同一時刻只被一個請求使用,只要我們每次使用之前,都設置成自己想要的內容,那就不會在使用的過程中被覆蓋。使用ThreadLocal最好是每次使用完就調用remove方法,將其刪掉,避免先get后set的情況導致業務的錯誤。
例子:
分庫 有3個庫 db1 db2 db3
web應用使用了線程池 假如有10個線程
request1請求到達web服務端的時候,經過分庫邏輯處理后,定位到的是db1,tomcat線程池分配的線程號是thread1,在給予thread1線程的threadlocal.set 保存的數據源是db1
由于tomcat線程池的線程是復用的,request2 恰巧tomcat給予該請求分配到的也是threade1,如果此時針對request2的請求,是不走分庫邏輯的,用到的是配置死的db2數據源,那么此時就會導致request2用到的是上個處理請求request1的thread1里面的threadlocal的數據源db1,此時就會導致邏輯錯誤,找不到相應的表的錯誤
關于ThreadLocal不調用remove方法會導致業務邏輯錯誤的示例分析就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。