特別注意,web容器的線程是重復使用的,web容器使用了線程池,當一個請求使用完某個線程,該線程會放回線程池被其它請求使用,這就導致一個問題,不同的請求還是有可能會使用到同一個線程(只要請求數量大於線程數量),而ThreadLocal是屬於線程的,
如果我們使用完ThreadLocal對象而沒有手動刪掉,那么后面的請求就有機會使用到被使用過的ThreadLocal對象!
這時候分情況考慮了:
1此請求在使用ThreadLocal的時候,是先get()來判斷然后再set(),那就會有問題。因為get到的是別的請求set的內容,
2此請求在使用ThreadLocal,都是先set再get,那就不會有問題,因為一個線程同一時刻只被一個請求使用,只要我們每次使用之前,都設置成自己想要的內容,那就不會在使用的過程中被覆蓋。
使用ThreadLocal最好是每次使用完就調用remove方法,將其刪掉,避免先get后set的情況導致業務的錯誤。
第二點,不remove的話容易造成堆棧內存溢出。
線程池重用線程時,會對ThreadLocal
的值進行清空嗎?
《Java並發編程實戰》一書的第8章時,有如下一句話:
只有當線程本地值的生命周期受限於任務的生命周期時,在線程池的線程中使用
ThreadLocal
才有意義,而在線程池的線程中不應該使用ThreadLocal
在任務之間傳遞值。
------------
不會清空,要你自己去清空。
ask指的是一個Thread所執行的任務。
總之就是告訴你,如果你能夠在使用ThreadLocal的時候管理它的創建、銷毀,那么就可以用,否則會出問題。原因是ThreadLocal是和Thread綁定的,如果Thread是從Thread Pool中拿出來的,那么意味着Thread可能會被復用,如果被復用,你就一定得保證這個Thread上一次結束的時候,其關聯的ThreadLocal被清空掉,否則就會串到下一次使用。