《Android開發藝術探索》讀書筆記——Handler訊息機制(ThreadLocal)
阿新 • • 發佈:2019-02-17
ThreadLocal
ThreadLocal是一個執行緒內部的資料儲存類。它可以為各執行緒儲存資料,同時只能由當前執行緒獲取到儲存的資料,對於其他執行緒來說則獲取不到。它可以在不同執行緒中維護一套資料的副本,並且彼此互不干擾。
一言不合上程式碼:
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(); public static void main(String[] args) { threadLocal.set(1); System.out.println(Thread.currentThread().getName() + "--value:" + threadLocal.get()); new Thread("Thread#1") { public void run() { threadLocal.set(2); System.out.println(Thread.currentThread().getName() + "--value:" + threadLocal.get()); }; }.start(); new Thread("Thread#2") { public void run() { System.out.println(Thread.currentThread().getName() + "--value:" + threadLocal.get()); }; }.start(); }
輸出結果為:
main--value:1
Thread#1--value:2
Thread#2--value:null
ThreadLocal內部為當前執行緒維護了一個ThreadLocalMap。key是ThreadLocal物件,value則是需要設定的值,儲存在Entry中。
注意
Handler建立時,會獲取到訊息佇列和當前執行緒的Looper物件來構建訊息迴圈系統,那麼如何獲取到當前執行緒的Looper呢?就是用到ThreadLocal,它儲存了Looper物件。保證了不同執行緒間提供對應的Looper物件。
因此保證了一個執行緒只有一個Looper物件
注意:執行緒是預設沒有Looper的,如果需要使用Handler,就必須為執行緒建立Looper。
只所以可以在Activity中直接例項化Handler,是因為ActivityThread作為程式的入口,已經例項化好了Looper物件。
public final class ActivityThread { // 省略... public static void main(String[] args) { // 省略... Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); } }
因此如果需要在子執行緒中使用Handler,則必須先例項化Looper。
new Thread("Thread#1"){
@Override
public void run() {
Looper.prepare();
Handler handler = new Handler();
handler.sendEmptyMessage(0);
Looper.loop();
}
}.start();