1. 程式人生 > >ThreadLocal的理解與應用場景分析

ThreadLocal的理解與應用場景分析

位置 理解 原理 解釋 als 存取 cti 只需要 his

對於Java ThreadLocal的理解與應用場景分析

一、對ThreadLocal理解

ThreadLocal提供一個方便的方式,可以根據不同的線程存放一些不同的特征屬性,可以方便的在線程中進行存取。

二、以session為例來理解ThreadLocal

  在web開發的session中,不同的線程對應不同的session,那麽如何針對不同的線程獲取對應的session呢?

  我們可以設想了如下兩種方式:

  1.action中創建session,然後傳遞給ServiceService再傳遞給Dao,很明顯,這種方式將使代碼變得臃腫復雜。

  2.創建一個靜態的map,鍵對應我們的線程,值對應

session,當我們想獲取session時,只需要獲取map,然後根據當前的線程就可以獲取對應的值。

  我們看看Hibernate中是如何實現這種情況的:

   技術分享

  在Hibernate中是通過使用ThreadLocal來實現的。在getSession方法中,如果ThreadLocal存在session,則返回session,否則創建一個session放入ThreadLocal中。

  總結一下就是在ThreadLocal中存放了一個session

為什麽我們在ThreadLocal存放一個session,這個session就會與一個線程對應呢?

  實際上ThreadLocal中並沒有存放任何的對象或引用,在上面的的代碼中

ThreadLocal的實例threadSession只相當於一個標記的作用。而存放對象的真正位置是正在運行的Thread線程對象,每個Thread對象中都存放著一個ThreadLocalMap類型threadLocals對象,這是一個映射表map,這個map的鍵是一個ThreadLocal對象,值就是我們想存的局部對象。

  我們以上面的代碼為例分析一下:

  當我們往ThreadLocal中存放變量的時候發生了什麽?

  即這行代碼時。

  技術分享

我們看下ThreadLocal的源碼中set()方法的實現。

技術分享

如果把這些代碼簡化的話就一句

  Thread.currentThread().threadLocals.set(this,value);

  Thread.currentThread()獲取當前的線程

  threadLocals就是我們上面說的每個線程對象中用於存放局部對象的map

  所以set()就是獲取到當前線程的map然後把值放進去,我們發現鍵是this,也就是當前的ThreadLocal對象,可以發現ThreadLocal對象就是一個標記的作用,我們根據這個標記找到對應的局部對象。

  如果對比get()方法,可以發現原理都差不多,都是對線程中的threadLocals這個map的操作,我就不解釋了。

  ThreadLocal就是一個標記的作用,當我們在線程中使用ThreadLocalset()或者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的理解與應用場景分析