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();複製程式碼