ThreadLocal
看名字好像是一個Thread的實現,其實並非這樣的,ThreadLocal並不是是一個線程的本地實現版本,它並非一個Thread,而是線程局部 (thread-local) 變量。這些變量不一樣於它們的普通對應物,由於訪問某個變量(經過其 get 或 set 方法)的每一個線程都有本身的局部變量,它獨立於變量的初始化副本。ThreadLocal 實例一般是類中的 private static 字段,它們但願將狀態與某一個線程(例如,用戶 ID 或事務 ID)相關聯。java
線程局部變量其實的功用很是簡單,就是爲每個使用該變量的線程都提供一個變量值的副本,是Java中一種較爲特殊的線程綁定機制,使每個線程均可以獨立地改變本身的副本,而不會和其它線程的副本衝突。多線程
從線程的角度看,每一個線程都保持一個對其線程局部變量副本的隱式引用,只要線程是活動的而且 ThreadLocal 實例是可訪問的;在線程消失以後,其線程局部實例的全部副本都會被垃圾回收(除非存在對這些副本的其餘引用)。併發
方法名 | 說明 |
---|---|
ThreadLocal() | 建立一個線程本地變量 |
返回值 | 方法名 | 說明 |
---|---|---|
T | get() | 返回此線程局部變量的當前線程副本中的值 |
protected T | initialValue() | 返回此線程局部變量的當前線程的「初始值」 |
void | remove() | 移除此線程局部變量當前線程的值 |
void | set(T value) | 將此線程局部變量的當前線程副本中的值設置爲指定值 |
import java.util.Random; /** * ThreadLocal測試 * * @author jianggujin * */ public class ThreadLocalDemo implements Runnable { private final static ThreadLocal<People> threadLocal = new ThreadLocal<People>(); public static void main(String[] agrs) { ThreadLocalDemo td = new ThreadLocalDemo(); Thread t1 = new Thread(td); Thread t2 = new Thread(td); t1.start(); t2.start(); } public void run() { accessStudent(); } public void accessStudent() { // 獲取當前線程的名字 String currentThreadName = Thread.currentThread().getName(); System.out.println(currentThreadName + " is running!"); // 產生一個隨機數並打印 Random random = new Random(); int age = random.nextInt(100); System.out.println("thread " + currentThreadName + " set age to:" + age); People people = getPeople(); people.setAge(age); System.out.println("thread " + currentThreadName + " first read age is:" + people.getAge()); try { Thread.sleep(500); } catch (InterruptedException ex) { ex.printStackTrace(); } System.out.println("thread " + currentThreadName + " second read age is:" + people.getAge()); } protected People getPeople() { People people = threadLocal.get(); // 線程首次執行此方法的時候,threadLocal.get()確定爲null if (people == null) { // 建立一個對象,並保存到本地線程變量threadLocal中 people = new People(); threadLocal.set(people); } return people; } } class People { private int age = 0; public int getAge() { return this.age; } public void setAge(int age) { this.age = age; } }
ThreadLocal使用場合主要解決多線程中數據數據因併發產生不一致問題。ThreadLocal爲每一個線程的中併發訪問的數據提供一個副本,經過訪問副原本運行業務,這樣的結果是耗費了內存,可是大大減小了線程同步所帶來性能消耗(空間換時間),也減小了線程併發控制的複雜度。dom