2011-10-02 30 views
1

我正在閱讀ThreadLocal類文檔,並想知道它可以在哪些場景下使用。目的和使用ThreadLocal類?

首先我認爲這可以在那些我們有第三方/遺留類場景中使用,我們要處理同步問題。然後我查看了ThreadLocal的其他例子,發現ThreadLocal在那裏不會幫助,因爲在大多數情況下,我們有單個對象,它在所有線程中共享。它是否正確?

有了進一步的理解,現在我可以考慮在那些需要每個線程需要單獨對象的場景中使用ThreadLocal類,並且如果特定線程與ThreadLocal中的對象交互,每次都會使用同一個對象,而不是創造一個新的。

這是正確的還是我錯過了什麼?

回答

10

ThreadLocal的最常用於實現在應用服務器或其中,每個用戶/客戶端請求是由一個單獨的線程來處理servlet容器每個請求的全局變量。

例如,彈簧,彈簧安全性和JSF都有通過這些框架的功能訪問的「上下文」的概念。並且在每種情況下,在無法使用或不會使用DI的情況下,通過依賴注入(乾淨方式)將該上下文實現爲ThreadLocal

這是不好的可維護性,因爲它隱藏的依賴,因爲這樣的容器使用線程池也直接導致的問題。他們必須使用反射來刪除請求之間的所有ThreadLocal實例,以避免來自一個請求的數據在另一個請求中出現(可能導致令人討厭的安全問題)。有時它也會導致內存泄漏。

基本上,它是一種功能,可以在hackish的方式非常有用,但也很危險。如果可能,我建議你避免它。

+0

感謝Michael..As ......。這裏是我的我的理解,我們通常不保留servlet中的全局變量,因爲它們將在跨線程中可見,這是危險的。所以threadlocal提供了一種方式,其中變量對每個特定的線程都是全局的。對? –

+0

@Mohit:基本上是的。 –

0

另一個常用的應用程序是針對需要同步的對象的每線程緩存,但必須避免開銷。

例如:SimpleDateFormat不是線程安全的 - 沒有Format是。始終創建新實例效率不高。在多線程環境中同步一個實例也是無效的。解決的辦法是這樣的:你說的ThreadLocal是最常見的用於實現應用服務器或servlet容器每個請求的全局變量

class Foo 
    private final static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>(){ 
     protected SimpleDateFormat initialValue() { 
      return new SimpleDateFormat(pattern); 
     } 
    }; 
    public void doStuff(){ 
     SimpleDateFormat df = threadLocal.get(); 
     // use df 
    } 
} 
+1

我不確定這是否是更好的性能方案。訪問ThreadLocal並不是簡單或廉價的操作。 –

+0

在一邊查看'ThreadLocal.get()'的來源,並在另一邊通過構造函數'SimpleDateFormat(String)'查看其他內容。另外[這個問題](http://stackoverflow.com/questions/609826/performance-of-threadlocal-variable)支持我的觀點。 –

+0

你還看過'ThreadLocalMap'的來源嗎?我所說的是,決定應該基於基準或者(更好)分析而不是假設,這是非常不重要的。如果你有數據支持你的建議,太好了。 –