最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android Handler runWithScissors 梳理流程解析

 更新時(shí)間:2022年10月21日 14:30:44   作者:345丶  
這篇文章主要為大家介紹了Android Handler runWithScissors 梳理流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

看 WMS 代碼的時(shí)候看到了 Handler.runWithScissors 方法,所以來惡補(bǔ)一下

public static WindowManagerService main(final Context context, final InputManagerService im,final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,Supplier<Surface> surfaceFactory,
            Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
        DisplayThread.getHandler().runWithScissors(() ->
                sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
                        atm, transactionFactory, surfaceFactory, surfaceControlFactory), 0);
        return sInstance;
}

通過 DisplayThread.getHandler() 調(diào)用了 runWithScissors 方法。

該方法的設(shè)計(jì)初衷就是:在一個(gè)線程中通過 Handler 向另外一個(gè)線程發(fā)送消息,并等待另一個(gè)線程處理完成后再繼續(xù)執(zhí)行。

runWithScissors

首先來看一下官方文檔的描述:

同步運(yùn)行指定的任務(wù)。如何當(dāng)前線程和處理線程相同,則立即執(zhí)行不用排隊(duì),否則就發(fā)送到別的線程進(jìn)行處理,并等待他完成后再返回。另外,這種方法很危險(xiǎn),使用不當(dāng)可能會造成死鎖,畢竟是兩個(gè)線程間的通信。

還有該方法被標(biāo)記為 @hide,因?yàn)橛幸恍╇[患,所以該方法不希望被開發(fā)者使用,一般都用于 Framwork 層。

下面我們來分析一下代碼:

public final boolean runWithScissors(@NonNull Runnable r, long timeout) {
    if (r == null) {
        throw new IllegalArgumentException("runnable must not be null");
    }
    if (timeout < 0) {
        throw new IllegalArgumentException("timeout must be non-negative");
    }
    if (Looper.myLooper() == mLooper) {
        r.run();
        return true;
    }
    BlockingRunnable br = new BlockingRunnable(r);
    return br.postAndWait(this, timeout);
}

首先獲取當(dāng)前線程的 looper,在拿到 Handler 所屬的looper,如果是同一個(gè),就直接執(zhí)行并返回 true,否則就繼續(xù)往下走。

如果所屬的 looper 不相同,則使用 BlockingRunnable 進(jìn)行包裝,并調(diào)用 postAndWait 方法:

private static final class BlockingRunnable implements Runnable {
    private final Runnable mTask;
    private boolean mDone;
    public BlockingRunnable(Runnable task) {
        mTask = task;
    }
    @Override
    public void run() {
        try {
            mTask.run();//運(yùn)行在 handler 線程
        } finally {
            synchronized (this) {
                mDone = true; //標(biāo)記完成
                notifyAll(); //喚醒線程
            }
        }
    }
    public boolean postAndWait(Handler handler, long timeout) {
        //使用 post 進(jìn)行發(fā)送
        if (!handler.post(this)) {
            return false;
        }
        synchronized (this) {
            if (timeout > 0) {
                final long expirationTime = SystemClock.uptimeMillis() + timeout;
                while (!mDone) {
                    long delay = expirationTime - SystemClock.uptimeMillis();
                    if (delay <= 0) {
                        return false; // timeout
                    }
                    try {
                        wait(delay);
                    } catch (InterruptedException ex) {
                    }
                }
            } else {
                while (!mDone) {
                    try {
                        wait();
                    } catch (InterruptedException ex) {
                    }
                }
            }
        }
        return true;
    }
}

在 postAndWait 方法中,首先調(diào)用 post 添加到 queue 隊(duì)列中,如果成功返回 true,如果發(fā)送失敗,postAndWait 方法直接退出。

發(fā)送成功后,就會添加的隊(duì)里中,等到合適的時(shí)候 run 方法就會執(zhí)行,然后就會執(zhí)行 finally 塊,將 mDone 置為 true。

post() 方法執(zhí)行成功后,就會進(jìn)入 synchronized 代碼塊,需要注意的是 run 方法中也有一個(gè) synchronized,這兩個(gè)鎖對象都是 this,所以說,同一時(shí)刻只能有一個(gè)代碼塊被執(zhí)行,另一個(gè)只能進(jìn)行等待。

接著就是 timeout 大于 0 并且 mDone 標(biāo)志一直處于 false,則進(jìn)行 wait 等待,等待結(jié)束后如果任務(wù)還沒有完成,直接 return false,表示任務(wù)失敗。

如果 timeout 小于0,則不需要延時(shí),直接進(jìn)行阻塞,沒有超時(shí)時(shí)間,只能等待被喚醒。

最后 return true 表示任務(wù)成功。

梳理流程

1,首先判斷目標(biāo)線程和當(dāng)前線程是否相同,相同則立即執(zhí)行任務(wù),return true。

2,接著就使用 BlockingRunnable 進(jìn)行包裝,然后使用 post 發(fā)送。發(fā)送失敗表示目標(biāo)線程的 Looper 有問題,直接 return false, 表示任務(wù)失敗。

3,發(fā)送成功以后,會有兩個(gè)分支,一個(gè)是 run 方法中的 synchronized,還有一個(gè)是 postAndWait 中的synchronized 。這兩個(gè)在同一時(shí)刻只能有一個(gè)執(zhí)行。run 方法中執(zhí)行任務(wù),postAndWait 中進(jìn)行延時(shí)或者直接等待。

4,最后就是延時(shí)等待結(jié)束后任務(wù)沒完成則表示任務(wù)失敗,如果沒有延時(shí)就直接進(jìn)行 wait 進(jìn)行阻塞,直到被喚醒。這里沒有超時(shí)邏輯,會存在一定的問題。

存在的問題

通過上面的分析,我們大底可以分析出問題的關(guān)鍵了,具體如下所示:

  • 沒有超時(shí)取消邏輯
  • 延時(shí)完成后,任務(wù)如果沒有完成,直接回 return false,但是 Runable 依然在運(yùn)行在目標(biāo)線程的 MessageQueue 中,最終依然會得到執(zhí)行,但是不會符合我們的預(yù)期

死鎖

1,如果 Runable 在沒有執(zhí)行的時(shí)候被移除了,例如 Handler.removeCallBack,Looper.quit,這個(gè)任務(wù)就永遠(yuǎn)得不到執(zhí)行,就會導(dǎo)致 wait 一直等待。

2,如果 wait 一直無法被喚醒, 并且這個(gè)時(shí)候還持有者別的鎖,就會導(dǎo)致死鎖。

那么要如何解決呢,上面第一種也無需解決,如果它不符合你的業(yè)務(wù),你也就不需要使用它了,第二種只需要保證當(dāng)前線程沒有別的鎖,而且 looper 不能直接退出,需要退出的時(shí)候也需要安全退出(quitSafely方法)。

總結(jié)

通過分析我們也可以看出來 runWithScissors 方法基本上不是偏向于業(yè)務(wù)的,而是偏向于 framwork 層的,因此該方法被標(biāo)注為了 hide 方法。如果我們業(yè)務(wù)真的需要使用這個(gè)方法,我們也完全可以仿照源碼自己寫一個(gè)出來,并且還可以隨意修改,豈不美滋滋。

以上就是Android Handler runWithScissors 梳理流程解析的詳細(xì)內(nèi)容,更多關(guān)于Android Handler runWithScissors 的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • android中okhttp實(shí)現(xiàn)斷點(diǎn)上傳示例

    android中okhttp實(shí)現(xiàn)斷點(diǎn)上傳示例

    本篇文章主要介紹了android中okhttp實(shí)現(xiàn)斷點(diǎn)上傳示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • Android DynamicGrid實(shí)現(xiàn)拖曳交換位置功能

    Android DynamicGrid實(shí)現(xiàn)拖曳交換位置功能

    這篇文章主要為大家詳細(xì)介紹了Android DynamicGrid實(shí)現(xiàn)拖曳交換位置功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • 淺析Android錄屏 MediaRecorder

    淺析Android錄屏 MediaRecorder

    MediaRecorder類是Android sdk提供的一個(gè)專門用于音視頻錄制,一般利用手機(jī)麥克風(fēng)采集音頻,攝像頭采集圖片信息。這篇文章主要介紹了Android錄屏 MediaRecorder介紹,需要的朋友可以參考下
    2020-03-03
  • Android仿微博加載長圖滾動查看效果

    Android仿微博加載長圖滾動查看效果

    這篇文章主要為大家詳細(xì)介紹了Android仿微博加載長圖滾動查看效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • android與asp.net服務(wù)端共享session的方法詳解

    android與asp.net服務(wù)端共享session的方法詳解

    這篇文章主要給大家介紹了關(guān)于android與asp.net服務(wù)端如何共享session的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)下吧。
    2017-09-09
  • View觸發(fā)機(jī)制API實(shí)現(xiàn)GestureDetector OverScroller詳解

    View觸發(fā)機(jī)制API實(shí)現(xiàn)GestureDetector OverScroller詳解

    這篇文章主要為大家介紹了View觸發(fā)機(jī)制API實(shí)現(xiàn)GestureDetector OverScroller詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • android控件實(shí)現(xiàn)多張圖片漸變切換

    android控件實(shí)現(xiàn)多張圖片漸變切換

    這篇文章主要為大家詳細(xì)介紹了android控件實(shí)現(xiàn)多張圖片漸變切換,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • Android TV listview及焦點(diǎn)處理

    Android TV listview及焦點(diǎn)處理

    這篇文章主要介紹了Android TV listview及焦點(diǎn)處理的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Android多線程處理機(jī)制中的Handler使用介紹

    Android多線程處理機(jī)制中的Handler使用介紹

    本文將為大家介紹下Android的Handler的使用方法,Handler可以發(fā)送Messsage和Runnable對象到與其相關(guān)聯(lián)的線程的消息隊(duì)列,感興趣的朋友可以了解下哈
    2013-06-06
  • Android實(shí)現(xiàn)視頻播放--騰訊瀏覽服務(wù)(TBS)功能

    Android實(shí)現(xiàn)視頻播放--騰訊瀏覽服務(wù)(TBS)功能

    TBS視頻播放器可以支持市面上幾乎所有的視頻格式,包括mp4, flv, avi, 3gp, webm, ts, ogv, m3u8, asf, wmv, rm, rmvb, mov, mkv等18種視頻格式。這篇文章主要介紹了Android實(shí)現(xiàn)視頻播放--騰訊瀏覽服務(wù)(TBS),需要的朋友可以參考下
    2018-07-07

最新評論

久治县| 庐江县| 宁武县| 潍坊市| 麟游县| 阿拉尔市| 丰县| 郸城县| 鹤峰县| 巴楚县| 洱源县| 桂阳县| 邵阳县| 松阳县| 商南县| 明溪县| 油尖旺区| 深圳市| 合山市| 金门县| 海盐县| 清水河县| 密云县| 房产| 永济市| 南投市| 荔浦县| 漯河市| 金塔县| 尚义县| 桃源县| 南陵县| 丹江口市| 阳信县| 乐清市| 洪雅县| 鄂尔多斯市| 榆中县| 武胜县| 醴陵市| 藁城市|