看jdk 源碼說明:
* This class provides thread-local variables. These variables differ from
* their normal counterparts in that each thread that accesses one (via its
* <tt>get</tt> or <tt>set</tt> method) has its own, independently initialized
* copy of the variable. <tt>ThreadLocal</tt> instances are typically private
* static fields in classes that wish to associate state with a thread (e.g.,
* a user ID or Transaction ID).
ThreadLocal,很多地方叫做線程本地變量,也有些地方叫做線程本地存儲,其實意思差不多。ThreadLocal爲變量在每個線程中都創建了一個拷貝,那麼每個線程可以訪問自己內部的副本變量。ThreadLocal典型的應用是 作爲一個靜態變量與多線程訪問的目標對象進行關聯,看JDK 自帶的舉例:
* public class ThreadId {
* // Atomic integer containing the next thread ID to be assigned
* private static final AtomicInteger nextId = new AtomicInteger(0);
*
* // Thread local variable containing each thread's ID
* private static final ThreadLocal<Integer> threadId =
* new ThreadLocal<Integer>() {
* @Override protected Integer initialValue() {
* return nextId.getAndIncrement();
* }
* };
*
* // Returns the current thread's unique ID, assigning it if necessary
* public static int get() {
* return threadId.get();
* }
* }
把代碼補充完成,如下:
public class TestTreadLocal {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread t1=new MyThread();
MyThread t2=new MyThread();
MyThread t3=new MyThread();
t1.start();t2.start();t3.start();
}
}
class ThreadId{
private static final AtomicInteger nextId = new AtomicInteger(0);
// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId =new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return nextId.getAndIncrement();
}
};
// Returns the current thread's unique ID, assigning it if necessary
public static int get() {
return threadId.get();
}
}
class MyThread extends Thread{
ThreadId t=new ThreadId();//無論創建多少個對象,因爲裏面的變量是static 的,只會創建一次
public void run(){
System.out.println(Thread.currentThread().getName()+" "+t.get());
}
}
分析一下代碼,多個線程與ID進行綁定,在每個線程啓動的時候,調用ThreadId的get 方法,該方法本來是返回一個ID,但是這裏使用了ThreadLocal 對象,並且在創建ThreadLocal對象的時候重寫了初始化方法,返回ID當前值並且自增。
查看ThreadLocal的get 方法
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
首先判斷當前線程對象在ThreadLocalMap裏是否存在,如果存在,則返回value,如果不存在,調用setInitialValue方法
進一步查看setInitialValue方法private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
首先調用初始化方法,由於我們在創建ThreadLocal 對象的時候重寫了該方法,所以這裏的value首先是0(可以理解爲第一個線程對象啓動),然後判斷當前線程對象是否在ThreadLocalMap裏存在,如果存在,則綁定線程對象與值(0),如果不存在,則創建,重新綁定,返回值數據(0);
目前由於基礎比較薄弱,對於該類的使用不甚了了,所以從網上找了幾篇文章,關於ThreadLocal 的使用與理解,可以用來參考
1、http://www.cnblogs.com/dolphin0520/p/3920407.html
2、http://www.iteye.com/topic/103804
3、http://www.cnblogs.com/alphablox/archive/2013/01/20/2869061.html
4、http://blog.csdn.net/lufeng20/article/details/24314381/