亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

Thread、Handler和HandlerThread關(guān)系何在?

hankkin / 833人閱讀

摘要:總結(jié)的使用方法還是比較簡(jiǎn)單的,但是我們要明白一點(diǎn)的是如果一個(gè)線程要處理消息,那么它必須擁有自己的,并不是在哪里創(chuàng)建,就可以在哪里處理消息的。如果不用的話,需要手動(dòng)去調(diào)用和這些方法。

前言

前幾天看到一道面試題:Thread、Handler和HandlerThread有什么區(qū)別?,這個(gè)題目有點(diǎn)意思,對(duì)于很多人來(lái)說(shuō),可能對(duì)Thread和Handler很熟悉,主要涉及到Android的消息機(jī)制(Handler、Message、Looper、MessageQueue),詳見(jiàn)《 從Handler.post(Runnable r)再一次梳理Android的消息機(jī)制(以及handler的內(nèi)存泄露)》

但是這個(gè)HandlerThread是拿來(lái)做什么的呢?它是Handler還是Thread?我們知道Handler是用來(lái)異步更新UI的,更詳細(xì)的說(shuō)是用來(lái)做線程間的通信的,更新UI時(shí)是子線程與UI主線程之間的通信。那么現(xiàn)在我們要是想子線程與子線程之間的通信要怎么做呢?當(dāng)然說(shuō)到底也是用Handler+Thread來(lái)完成(不推薦,需要自己操作Looper),Google官方很貼心的幫我們封裝好了一個(gè)類(lèi),那就是剛才說(shuō)到的:HandlerThread。(類(lèi)似的封裝對(duì)于多線程的場(chǎng)景還有AsyncTask)

使用方法

還是先來(lái)看看HandlerThread的使用方法:
首先新建HandlerThread并且執(zhí)行start()

private HandlerThread mHandlerThread;
......
mHandlerThread = new HandlerThread("HandlerThread");
handlerThread.start();

創(chuàng)建Handler,使用mHandlerThread.getLooper()生成Looper:

        final Handler handler = new Handler(mHandlerThread.getLooper()){
            @Override
            public void handleMessage(Message msg) {
                System.out.println("收到消息");
            }
        };

然后再新建一個(gè)子線程來(lái)發(fā)送消息:

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);//模擬耗時(shí)操作
                    handler.sendEmptyMessage(0);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

最后一定不要忘了在onDestroy釋放,避免內(nèi)存泄漏:

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandlerThread.quit();
    }

執(zhí)行結(jié)果很簡(jiǎn)單,就是在控制臺(tái)打印字符串:收到消息

原理

整個(gè)的使用過(guò)程我們根本不用去關(guān)心Handler相關(guān)的東西,只需要發(fā)送消息,處理消息,Looper相關(guān)的東西交給它自己去處理,還是來(lái)看看源碼它是怎么實(shí)現(xiàn)的,先看構(gòu)造方法:

public class HandlerThread extends Thread {}

HandlerThread其實(shí)還是一個(gè)線程,它跟普通線程有什么不同?

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    ......
}

答案是多了一個(gè)Looper,這個(gè)是子線程獨(dú)有的Looper,用來(lái)做消息的取出和處理。繼續(xù)看看HandlerThread這個(gè)線程的run方法:

    protected void onLooperPrepared() {
    }
    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();//生成Looper
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();//空方法,在Looper創(chuàng)建完成后調(diào)用,可以自己重寫(xiě)邏輯
        Looper.loop();//死循環(huán),不斷從MessageQueue中取出消息并且交給Handler處理
        mTid = -1;
    }

主要就是做了一些Looper的操作,如果我們自己使用Handler+Thread來(lái)實(shí)現(xiàn)的話也要進(jìn)行這個(gè)操作,再來(lái)看看getLooper()方法:

    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

方法很簡(jiǎn)單,就是加了個(gè)同步鎖,如果已經(jīng)創(chuàng)建了(isAlive()返回true)但是mLooper為空的話就繼續(xù)等待,直到mLooper創(chuàng)建成功,最后看看quit方法,值得一提的是有兩個(gè):

    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;
    }

quitSafely是針對(duì)在消息隊(duì)列中還有消息或者是延遲發(fā)送的消息沒(méi)有處理的情況,調(diào)用這個(gè)方法后都會(huì)被停止掉。

總結(jié)

HandlerThread的使用方法還是比較簡(jiǎn)單的,但是我們要明白一點(diǎn)的是:如果一個(gè)線程要處理消息,那么它必須擁有自己的Looper,并不是Handler在哪里創(chuàng)建,就可以在哪里處理消息的。

如果不用HandlerThread的話,需要手動(dòng)去調(diào)用Looper.prepare()和Looper.loop()這些方法。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/68693.html

相關(guān)文章

發(fā)表評(píng)論

0條評(píng)論

hankkin

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<