ThreadLocal的理解與應用場景分析
對於Java ThreadLocal的理解與應用場景分析
一、對ThreadLocal理解
ThreadLocal提供一個方便的方式,可以根據不同的線程存放一些不同的特征屬性,可以方便的在線程中進行存取。
二、以session為例來理解ThreadLocal
在web開發的session中,不同的線程對應不同的session,那麽如何針對不同的線程獲取對應的session呢?
我們可以設想了如下兩種方式:
1.在action中創建session,然後傳遞給Service,Service再傳遞給Dao,很明顯,這種方式將使代碼變得臃腫復雜。
2.創建一個靜態的map,鍵對應我們的線程,值對應
我們看看Hibernate中是如何實現這種情況的:
在Hibernate中是通過使用ThreadLocal來實現的。在getSession方法中,如果ThreadLocal存在session,則返回session,否則創建一個session放入ThreadLocal中。
總結一下就是在ThreadLocal中存放了一個session。
為什麽我們在ThreadLocal存放一個session,這個session就會與一個線程對應呢?
實際上ThreadLocal中並沒有存放任何的對象或引用,在上面的的代碼中
我們以上面的代碼為例分析一下:
當我們往ThreadLocal中存放變量的時候發生了什麽?
即這行代碼時。
我們看下ThreadLocal的源碼中set()方法的實現。
如果把這些代碼簡化的話就一句
Thread.currentThread().threadLocals.set(this,value);
Thread.currentThread()獲取當前的線程
threadLocals就是我們上面說的每個線程對象中用於存放局部對象的map
所以set()就是獲取到當前線程的map然後把值放進去,我們發現鍵是this,也就是當前的ThreadLocal對象,可以發現ThreadLocal對象就是一個標記的作用,我們根據這個標記找到對應的局部對象。
如果對比get()方法,可以發現原理都差不多,都是對線程中的threadLocals這個map的操作,我就不解釋了。
ThreadLocal就是一個標記的作用,當我們在線程中使用ThreadLocal的set()或者get()方法時,其實是在操作我們線程自帶的threadLocals這個map,多個線程的時候自然就有多個map,這些map互相獨立,但是,這些map都是根據一個ThreadLocal對象(因為它是靜態的)來作為鍵存放。
這樣可以在多個線程中,每個線程存放不一樣的變量,我們通過一個ThreadLocal對象,在不同的線程(通過Thread.currentThread()獲取當前線程)中得到不同的值(不同線程的threadLocals不一樣)。
為什麽threadLocals要是一個map呢?
因為我們可能會在一個類中聲明多個ThreadLocal的實例,這樣就有多個標記,所以要使用map對應。
總結:
ThreadLocal就是用來在類中聲明的一個標記,然後通過這個標記就根據不同Thread對象存取值。
應用場景:
在線程中存放一些就像session的這種特征變量,會針對不同的線程,有不同的值。
參考博客:http://www.iteye.com/topic/103804
ThreadLocal的理解與應用場景分析