threadlocals_如何使用ThreadLocals射击自己
threadlocals
它將很好地啟動。 像大多數故事一樣。 您會發現一個新概念,并對其功能感到驚訝。 然后突然裝備了這把新錘子,一切開始看起來像釘子。 根據我們過去幾個月的經驗, java.lang.ThreadLocal真是一錘定音。
我想這全都歸結為ThreadLocal的工作原理。 通過范圍界定類推最容易理解這個概念。 以同樣的方式,您的Spring Bean可以處于容器,會話或請求范圍內。 ThreadLocal使您可以在Thread范圍內聲明對象。
您可以將任何對象設置為ThreadLocal,并且該對象在訪問該對象的線程中將具有全局作用域和局部作用域。 一開始可能很難理解,但讓我解釋一下:
- ThreadLocal可以全局訪問存儲在ThreadLocal中的值。 這意味著,如果您可以訪問代碼中的ThreadLocal引用,則可以從該線程內部的任何位置訪問其中存儲的值。 如果線程從多個類調用方法,則所有方法都可以看到其他方法設置的ThreadLocal變量(因為它們在同一線程中執行)。 該值無需顯式傳遞。 就像使用全局變量一樣。
- 存儲在ThreadLocal中的值是線程本地的,這意味著每個線程將擁有自己的ThreadLocal變量。 線程無法訪問/修改其他線程的ThreadLocal變量。
因此,在這里我們有理由慶祝–我們掌握著一個真正強大的概念。 通常,這是呈現有狀態類線程安全的最簡單方法。 并封裝非線程安全類,以便可以在多線程環境中安全地使用它們。 除了簡單之外,使用ThreadLocal存儲每個線程單個信息或每個線程上下文信息還包含有價值的信息–通過使用ThreadLocal ,很明顯,線程之間不共享存儲在ThreadLocal中的對象,從而簡化了任務確定類是否是線程安全的。 當您手頭有1,000,000行的代碼庫時,我們發現這并非易事。
另一方面,這個強大的概念在錯誤的手中會產生許多問題。 像其他任何濫用的設計概念一樣。 在過去的幾個月中,我們最經常遇到兩個問題:
- ThreadLocal使您可以使用變量,而無需將它們顯式傳遞給方法調用鏈。 在某些情況下可能有用。 但是你們那里創建了n層體系結構以抽象出不同的通信接口的人們。 然后從您的DAO對象中的ThreadLocals中獲取HttpServletRequest ……您在做這個決定時在吸煙嗎? 我們在研究這個特殊案例時花了幾個小時和第二雙眼睛。 但是無論如何-使用全球化的力量時要小心。 您最終在代碼中創建了意外的依賴關系。 您可能還記得–這不是明智的選擇。
- 使用ThreadLocal時,很容易在代碼中引入內存泄漏。 這很好地說明了類加載器周圍的復雜性。 如果要在應用程序服務器中部署代碼,則使用與應用程序服務器本身使用的類加載器不同的類加載器來加載/卸載應用程序類。 這本身還不錯。 但是,現在考慮到現代應用程序服務器也池化線程,而不是在每個HttpRequest上創建一個新線程,我們為問題奠定了基礎。
如果其中一個應用程序類將一個值存儲在ThreadLocal變量中,并且在完成手頭的任務之后沒有將其刪除,則該Object的副本將與Thread一起保留(來自應用程序服務器線程池)。 由于池化線程的壽命超過了應用程序的壽命,因此它將防止對象被垃圾回收,從而防止ClassLoader負責加載應用程序。 而且我們創建了一個泄漏,有機會以一種很好的舊java.lang.OutOfMemoryError:PermGen空間形式浮出水面。
因此,考慮到它可能造成的危害,我們應該避免使用ThreadLocal嗎? 約書亞·布洛赫(Joshua Bloch)十年前曾說過:
“您是否可以通過線程局部變量導致意外的對象保留? 你當然可以。 但是您也可以使用數組來執行此操作。 這并不意味著線程局部變量(或數組)是壞事。 只是您必須謹慎使用它們。 使用線程池需要格外小心。 隨意使用線程池與隨意使用線程局部變量可能會導致意外的對象保留,這在許多地方都已提到。 但是,將責任歸咎于線程本機是沒有根據的?!?
我傾向于同意布洛赫先生的觀點,并且不認為ThreadLocal是邪惡的創造。 但是我也確實認為這是許多人無法正確理解的概念。
本文的靈感主要收集在尋找一些令人討厭的錯誤的不眠之夜中。 但是在寫作時,以下資源也被證明是有益的:
- Veera Sundar 博客文章解釋了范圍界定
- Javin Paul關于ThreadLocal泄漏的摘要
- 約書亞·布洛赫(Joshua Bloch)對ThreadLocals的看法
參考: 如何與我們的JCG合作伙伴 Nikita Salnikov Tarnovski (來自Plumbr Blog博客) 一起使用ThreadLocals進行射擊 。
翻譯自: https://www.javacodegeeks.com/2013/01/how-to-shoot-yourself-in-foot-with-threadlocals.html
threadlocals
總結
以上是生活随笔為你收集整理的threadlocals_如何使用ThreadLocals射击自己的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 武大校长开学典礼盛赞华为Mate60 P
- 下一篇: 华为新品发布会预告视频:最大的阻力给我们