HandlerThread學習

HandlerThread 是一個封裝好的looper線程類。

從源碼看看
public class HandlerThread extends Thread {
int mPriority; // 線程優先級
int mTid = -1; // 修改線程優先級、調度策略時用來做線程唯一標識
Looper mLooper; // 與線程關聯的Looper

public HandlerThread(String name) {
    super(name);
    mPriority = Process.THREAD_PRIORITY_DEFAULT; // 設置默認優先級0
}

public HandlerThread(String name, int priority) {
    super(name);
    mPriority = priority;                        // 主動設置優先級
}

protected void onLooperPrepared() { //回調方法,looper開始前執行
}

@Override
public void run() {
mTid = Process.myTid();
Looper.prepare(); // 初始化一個Looper對象,然后存入到ThreadLocal中,將Looper和當前線成進行綁定,一一對應.
synchronized (this) { // 進入同步塊
mLooper = Looper.myLooper(); //得到當前線程的looper對象
notifyAll();//通知其他線程
}
Process.setThreadPriority(mPriority); // 設置線程優先級
onLooperPrepared(); // 回調重寫
Looper.loop(); // 一個死循環,不斷從MessageQueue取出消息,如有消息就處理,沒有就阻塞
mTid = -1; // 因為Looper.loop()是個死循環啊,執行到mTid = -1的時候,就是looper退出的時候
}

public Looper getLooper() {
    if (!isAlive()) { // 如果線程不是在存活狀態則直接返回null。
        return null;
    }
    
    synchronized (this) {
        while (isAlive() && mLooper == null) { // 進入同步塊,當條件不滿足時無限等待,
            try {                              // 直到mLooper被設置成有效值了才退出等待
                wait();                        // run方法里的notifyAll就是用來喚醒這里的
            } catch (InterruptedException e) { // 中斷異常
            }
        }
    }
    return mLooper; // 最后返回mLooper
}


public boolean quit() {
    Looper looper = getLooper();
    if (looper != null) {
        looper.quit();
        return true;
    }
    return false;
}

public boolean quitSafely() {
    Looper looper = getLooper();
    if (looper != null) {
        looper.quitSafely();
        return true;
    }
    return false;
}

void quit(boolean safe) {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}

    synchronized (this) {
        if (mQuitting) {
            return;
        }
        mQuitting = true;

        if (safe) {
            removeAllFutureMessagesLocked();
        } else {
            removeAllMessagesLocked();
        }

        // We can assume mPtr != 0 because mQuitting was previously false.
        nativeWake(mPtr);
    }

}

quit()和 quitSafely()的區別:
removeAllMessagesLocked()是把MessageQueue消息池中所有的消息全部清空,無論延遲與否
removeAllFutureMessagesLocked()是只清空延遲消息,非延遲消息派發出去讓Handler去處理。

異步handler的創建方式
Thread newThread = new Thread(new Runnable()
{
@Override
public void run() {
Looper.prepare();
Looper.loop();
}
});
newThread.start();
Handler handler = new Handler(newThread.getLooper());

當執行到Handler handler = new Handler(newThread.getLooper());的時候,newThread的looper可能還沒有創建好,會有線程同步的
問題。

總結:
1.不管調用哪個,Looper就不再接收新的消息,再通過Handler調用sendMessage發消息都只會返回false,Looper的quit方法從API Level 1就存在了,但是Looper的quitSafely方法從API Level 18才添加進來

2.HandlerThread本質是一個Thread,區別在于他在run()之后創建了一個含有消息隊列的Looper,這樣我們在子線程中創建Handler時候只需指定使用HandlerThread中的Looper,不用再調用Looper.prepare(),looper.loop(),并且做了同步的處理,簡化了操作。

3.另外Handler與Activity在同一個線程中,不能做耗時操作。HandlerThread是新的線程,可做耗時操作

舉例:
public class MainActivity extends Activity {

private Handler handlerthread;
private HandlerThread thread;

//創建主線程中的handler
private Handler handler = new Handler() {
    public void handleMessage(android.os.Message msg) {
        Message message = new Message();
        handlerthread.sendMessageDelayed(message, 1000);
        Log.d("wuc", "主線程");
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button bt_test = (Button)findViewById(R.id.bt_test);
    bt_test.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            handlerthread.sendEmptyMessage(1);
        }
    });

    thread = new HandlerThread("threadHandler");
    thread.start();
    handlerthread = new Handler(thread.getLooper()){
        @Override
        public void handleMessage(Message msg) {
            Message message = new Message();
            //handler每隔1秒向主線程發送一次消息。
            Log.d("wuc", "子線程");
            handler.sendMessageDelayed(message, 1000);
        }
    };
}

}

04-26 16:49:26.822 7349-7385/com.example.lyf.androidtext D/wuc: 子線程
04-26 16:49:27.822 7349-7349/com.example.lyf.androidtext D/wuc: 主線程
04-26 16:49:28.823 7349-7385/com.example.lyf.androidtext D/wuc: 子線程
04-26 16:49:29.826 7349-7349/com.example.lyf.androidtext D/wuc: 主線程
04-26 16:49:30.826 7349-7385/com.example.lyf.androidtext D/wuc: 子線程
04-26 16:49:31.827 7349-7349/com.example.lyf.androidtext D/wuc: 主線程
04-26 16:49:32.828 7349-7385/com.example.lyf.androidtext D/wuc: 子線程

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容