ThreadLocal的工作原理
概述
ThreadLocal是一個用來儲存執行緒內部資料的類,什麼意思呢?ThreadLocal 重點突出的是Local,也就是儲存的這個資料只有對應的執行緒才能訪問。其他的執行緒是訪問不到。哪個執行緒存,就只能哪個執行緒取。那是怎麼做到的呢?
- 以ThreadLocal物件為鍵,任意物件為值作為儲存結構;
- 然後把這個key-value 結構存入到ThreadLocalMap的物件中;
- 而實際上每個執行緒物件都有一個同樣型別的變數指向這個ThreadLocalMap物件,且是唯一的。
- 存取都是對這個map操作,這樣就實現了執行緒內部存取的策略。
原始碼分析(JDK5)
從概述中我們能看出來,真正實現儲存資料的是這個ThreadLocalMap,那這裡先不分析其的實現,暫且把他先理解成HashMap,便於分析。
-
我們從
set(T value)
開始分析public void set(T value) { Thread t = Thread.currentThread(); //1、獲取此方法的呼叫者執行緒 ThreadLocalMap map = getMap(t); //2.獲取與這個執行緒繫結的ThreadLocalMap物件 if (map != null) //3.判斷這個物件是否為空 map.set(this, value); //4.不為空,就儲存這個鍵值對 else createMap(t, value); //5.為空,就去建立這個map物件並儲存這個鍵值對 }
原始碼中可以看到對這個map物件進行了唯一性的操作,只有為空的時候才會去建立。
那再來去看一下這個
createMap(Thread t, T firstValue)
和getMap(Thread t)
void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }
把建立的這個物件賦值給了Thread物件的一個變數
t.threadLocals
ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
實際上就是獲取這個執行緒儲存的map物件。再來看一眼這個
threadLocals
在Thread中的定義 -
取值
get()
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { // 不為空,就從map中取出這個threadLocal為key的entry物件 ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); //當map為null時候,去初始化這個Map並返回null }
如果你對Map瞭解,那麼Entry的獲取就不難了。這裡姑且先這麼認為ThreadLocalMap就是hashmap以便於理解。
-
移除
remove()
public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); //1.獲得map if (m != null) //2.map不為空,從map中移除 m.remove(this); }
ThreadLocal工作原理可以簡單的概況為:
每個執行緒都會唯一繫結一個ThreadLocalMap的物件,用TheadLocal作為這個map的鍵,來存取值。
用法
public class MyClass {
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public static void main(String args[]) {
new Thread(new Runnable() {
@Override
public void run() {
threadLocal.set(1);
new A().get();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
threadLocal.set(10);
new A().get();
}
}).start();
}
static class A {
public void get() {
int data = threadLocal.get();
System.out.println("A from" + Thread.currentThread().getName() + " get data:" + data);
}
}
}
總結
ThreadLocal不是用來解決物件共享訪問問題的,而主要是提供了執行緒保持物件的方法和避免引數傳遞的方便的物件訪問方式。
-
使用場景,在Android中的Looper的儲存就是這個ThreadLocal的運用。
// sThreadLocal.get() will return null unless you've called prepare(). static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); } /** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static Looper myLooper() { return sThreadLocal.get(); }
將Looper這個物件儲存在對應的執行緒中,這樣保證了一個執行緒對應一個Looper。
- 那有關ThreadLocalMap內部是如何來存取資料的,關後更......
相關文章
- Android的訊息機制之ThreadLocal的工作原理Androidthread
- ThreadLocal原理分析thread
- ThreadLocal 原理分析thread
- ThreadLocal用法及原理thread
- ThreadLocal原理深入解析thread
- ThreadLocal及InheritableThreadLocal的原理剖析thread
- 原始碼|ThreadLocal的實現原理原始碼thread
- ThreadLocal的正確使用與原理thread
- Java中ThreadLocal的用法和原理Javathread
- ThreadLocal原理用法詳解ThreadLocal記憶體洩漏thread記憶體
- 【多執行緒】ThreadLocal原理執行緒thread
- JUC---ThreadLocal原理詳解thread
- 面試中的 ThreadLocal 原理和使用場景面試thread
- ThreadLocal的設計與使用(原理篇)thread
- ThreadLocal 原理和使用場景分析thread
- 併發——深入分析ThreadLocal的實現原理thread
- Threadlocal的使用以及實現原理總結thread
- Mirror 的工作原理
- Spark的工作原理Spark
- View的工作原理View
- HashMap的工作原理HashMap
- DHCP的工作原理
- tcmalloc的工作原理
- undo的工作原理
- OAuth的工作原理OAuth
- ThreadLocal原理記錄,別被坑了!!thread
- Feign的工作原理
- OSPF的基本工作原理
- LiveData的工作原理LiveData
- SOCKS代理的工作原理
- Go的web工作原理GoWeb
- Web Service 的工作原理Web
- tcmalloc的工作原理(一)
- Java HashMap的工作原理JavaHashMap
- Standby Database的工作原理Database
- 堆疊的工作原理
- 天線的工作原理
- 工作流引擎的工作原理與功能