該文主要用于自我總結(jié),提煉。語句未經(jīng)斟酌,存在冗余重復(fù)等情況。各人客官可移步個人主頁右下方的《原創(chuàng)技術(shù)博客》文集,里面是對外發(fā)布的一些技術(shù)博客。(咳咳,如果用的是移動設(shè)備,簡書好像還沒支持,只能自己找。。)
當(dāng)然也可繼續(xù)閱讀,如若有些地方生澀難懂。那。。那就給我發(fā)私信,我整理一下。( ●▽● )
判斷所在的線程是不是主線程
可以使用
if (Looper.getMainLooper()==Looper.myLooper()){
//是主線程
}else {
//不是主線程
}
這里的Looper.getMainLooper()得到的就是主線程的Looper實例。這沒有什么好說的。因為主線程的Looper在UI線程創(chuàng)建的時候(app啟動的時候)就調(diào)用了
Looper.prepare();//初始化Looper對象
Looper.loop();//啟動Looper
所以說,主線程的looper實例肯定是有的,并且已經(jīng)運行了。
那么工作線程(異步線程)呢?不好意思,異步線程初始化時并沒有綁定一個looper實例:
Threads by default do not have a message loop associated with them. Of course, the method works
所以如果一個工作線程沒有綁定looper,那么Looper.myLooper()返回的結(jié)果將是null。如果想綁定一個looper線程,并讓它運行,就需要:
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();//初始化Looper對象
Looper.loop();//啟動Looper
//做一些線程的其他邏輯
}
}).start();
我們看到上面Looper.myLooper(); Looper.prepare();Looper.loop();Looper的靜態(tài)方法中并沒有傳入指定線程,但是最終得到的就是所在線程的looper或操作所在線程的looper。這是怎么做到的呢?
這是因為在Looper內(nèi)部維護了一個ThreadLocal:
public class Looper {
static final ThreadLocal<looper> sThreadLocal = new ThreadLocal<looper>();
public static void prepare() {
prepare(true);
}
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));
}
...
}
我們知道,在某一個線程調(diào)用sThreadLocal.get()時,得到的是該線程的數(shù)據(jù)的looper。前面的提到的Looper.prepare()用來在本線程生成一個looper實例在這里的源碼中也體現(xiàn)出來了。就是new 一個looper,然后放到ThreadLocal中。并且保證了一個線程只能有一個looper實例。
todo
- 在一個線程調(diào)用ThreadLocal的get/set方法,為什么得到的就是當(dāng)前thread的值?
- Thread currentThread = Thread.currentThread();這樣能得到當(dāng)前線程的信息。
- 然后根據(jù)當(dāng)前線程的信息去ThreadLocal中拿線程對應(yīng)的值??梢詫hreadLocal理解為一塊存儲區(qū),將這一大塊存儲區(qū)分割為多塊小的存儲區(qū),每一個線程擁有一塊屬于自己的存儲區(qū),那么對自己的存儲區(qū)操作就不會影響其他線程。對于ThreadLocal,則每一小塊存儲區(qū)中就保存了與特定線程關(guān)聯(lián)的Looper。
- looper的looper()方法做了什么工作?