日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何用ThreadLocals射击自己

發(fā)布時間:2023/12/3 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何用ThreadLocals射击自己 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

它將很好地啟動。 像大多數(shù)故事一樣。 您會發(fā)現(xiàn)一個新概念,并對其功能感到驚訝。 然后突然裝備了這把新錘子,一切開始看起來像釘子。 根據(jù)我們過去幾個月的經(jīng)驗, java.lang.ThreadLocal真是一錘定音。

我想這全都?xì)w結(jié)為ThreadLocal的工作原理。 通過范圍界定類推最容易理解這個概念。 以同樣的方式,您的Spring Bean可以處于容器,會話或請求范圍內(nèi)。 ThreadLocal使您可以在Thread范圍內(nèi)聲明對象。

您可以將任何對象設(shè)置為ThreadLocal,并且該對象在訪問該對象的線程中將具有全局作用域和局部作用域。 首先可能會很復(fù)雜,但讓我解釋一下:

  • 線程可以全局訪問ThreadLocal中存儲的值。 這意味著,如果您可以訪問代碼中的ThreadLocal引用,則可以從該線程內(nèi)部的任何位置訪問其中存儲的值。 如果線程從多個類調(diào)用方法,則所有方法都可以看到其他方法設(shè)置的ThreadLocal變量(因為它們在同一線程中執(zhí)行)。 該值無需顯式傳遞。 就像使用全局變量一樣。
  • 存儲在ThreadLocal中的值是線程本地的,這意味著每個線程將擁有自己的ThreadLocal變量。 一個線程無法訪問/修改其他線程的ThreadLocal變量。

因此,在這里我們有一個值得慶祝的理由–我們手中有一個真正強(qiáng)大的概念。 這通常是呈現(xiàn)有狀態(tài)類線程安全的最簡單方法。 并封裝非線程安全類,以便可以在多線程環(huán)境中安全地使用它們。 除了簡單之外,使用ThreadLocal存儲每個線程單個信息或每個線程上下文信息還包含有價值的信息–通過使用ThreadLocal ,很明顯,線程之間不共享存儲在ThreadLocal中的對象,從而簡化了任務(wù)確定類是否是線程安全的。 當(dāng)您手頭有1,000,000行的代碼庫時,我們發(fā)現(xiàn)這并非易事。

另一方面,這個強(qiáng)大的概念在錯誤的手中會產(chǎn)生許多問題。 像其他任何濫用的設(shè)計概念一樣。 在過去的幾個月中,我們最經(jīng)常遇到兩個問題:

  • ThreadLocal使您可以使用變量,而無需在方法調(diào)用鏈中顯式傳遞它們。 在某些情況下可能有用。 但是你們那里創(chuàng)建了n層體系結(jié)構(gòu)以抽象出不同的通信接口的人們。 然后從您的DAO對象中的ThreadLocals中獲取HttpServletRequest ……您在做這個決定時在吸煙嗎? 我們在研究這個特定案例時花了幾個小時和第二雙眼睛。 但是無論如何-使用全球化的力量時要小心。 您最終在代碼中創(chuàng)建了意外的依賴關(guān)系。 您可能還記得–這不是明智的選擇。
  • 使用ThreadLocal時,很容易在代碼中引入內(nèi)存泄漏。 這很好地說明了類加載器周圍的復(fù)雜性。 如果要在應(yīng)用程序服務(wù)器中部署代碼,則將使用與應(yīng)用程序服務(wù)器本身使用的類加載器不同的類加載器加載/卸載應(yīng)用程序類。 這本身還不錯。 但是,現(xiàn)在考慮到現(xiàn)代應(yīng)用程序服務(wù)器也池化線程,而不是在每個HttpRequest上創(chuàng)建一個新線程,我們?yōu)閱栴}奠定了基礎(chǔ)。

如果其中一個應(yīng)用程序類將一個值存儲在ThreadLocal變量中,并且在手頭的任務(wù)完成后沒有將其刪除,則該Object的副本將與Thread一起保留(來自應(yīng)用程序服務(wù)器線程池)。 由于池化線程的壽命超過了應(yīng)用程序的壽命,因此它將防止該對象,從而使ClassLoader負(fù)責(zé)加載應(yīng)用程序而不會被垃圾回收。 而且我們創(chuàng)建了一個泄漏,有機(jī)會以一種很好的舊java.lang.OutOfMemoryError:PermGen空間形式浮出水面。

因此,考慮到它可能造成的危害,我們應(yīng)該避免使用ThreadLocal嗎? 約書亞·布洛赫(Joshua Bloch)十年前曾說過:

“您是否可以通過線程局部變量導(dǎo)致意外的對象保留? 你當(dāng)然可以。 但是您也可以使用數(shù)組來執(zhí)行此操作。 這并不意味著線程局部變量(或數(shù)組)是壞事。 只是您必須謹(jǐn)慎使用它們。 使用線程池需要格外小心。 隨意使用線程池與隨意使用線程本地變量相結(jié)合會導(dǎo)致意外的對象保留,這在許多地方都已提到。 但是,將責(zé)任歸咎于線程本機(jī)是沒有根據(jù)的。”

我傾向于同意布洛赫先生的觀點,并且不認(rèn)為ThreadLocal是邪惡的創(chuàng)造。 但是我也確實認(rèn)為這是許多人無法正確理解的概念。

本文的靈感主要收集在尋找一些令人討厭的錯誤的不眠之夜中。 但是在寫作時,以下資源也被證明是有益的:

  • Veera Sundar 博客文章解釋了范圍界定
  • Javin Paul關(guān)于ThreadLocal泄漏的摘要
  • Joshua Bloch對ThreadLocals的看法

參考: 如何與我們的JCG合作伙伴 Nikita Salnikov Tarnovski (來自Plumbr Blog博客) 一起使用ThreadLocals進(jìn)行射擊 。

翻譯自: https://www.javacodegeeks.com/2013/01/how-to-shoot-yourself-in-foot-with-threadlocals.html

總結(jié)

以上是生活随笔為你收集整理的如何用ThreadLocals射击自己的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。