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

Kotlin圖文并茂講解續(xù)體與續(xù)體攔截器和調(diào)度器

 更新時(shí)間:2022年08月01日 11:40:04   作者:LeeDuo.  
這篇文章主要介紹了Kotlin開發(fā)中續(xù)體與續(xù)體攔截器和調(diào)度器的相關(guān)使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一.Continuation

Continuation接口是協(xié)程中最核心的接口,代表著掛起點(diǎn)之后的續(xù)體,代碼如下:

public interface Continuation<in T> {
    // 續(xù)體的上下文
    public val context: CoroutineContext
    // 該方法用于恢復(fù)續(xù)體的執(zhí)行
    // result為掛起點(diǎn)執(zhí)行完成的返回值,T為返回值的類型
    public fun resumeWith(result: Result<T>)
}

Continuation圖解

二.ContinuationInterceptor

ContinuationInterceptor接口繼承自Element接口,是協(xié)程中的續(xù)體攔截器,代碼如下:

public interface ContinuationInterceptor : CoroutineContext.Element {
    // 攔截器的Key
    companion object Key : CoroutineContext.Key<ContinuationInterceptor>
    // 攔截器對(duì)續(xù)體進(jìn)行攔截時(shí)會(huì)調(diào)用該方法,并對(duì)continuation進(jìn)行緩存
    // 攔截判斷:根據(jù)傳入的continuation對(duì)象與返回的continuation對(duì)象是否相同
    public fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T>
    // 當(dāng)interceptContinuation方法攔截的協(xié)程執(zhí)行完畢后,會(huì)調(diào)用該方法
    public fun releaseInterceptedContinuation(continuation: Continuation<*>) {
        /* do nothing by default */
    }
    // get方法多態(tài)實(shí)現(xiàn)
    public override operator fun <E : CoroutineContext.Element> get(key: CoroutineContext.Key<E>): E? {
        @OptIn(ExperimentalStdlibApi::class)
        if (key is AbstractCoroutineContextKey<*, *>) {
            @Suppress("UNCHECKED_CAST")
            return if (key.isSubKey(this.key)) key.tryCast(this) as? E else null
        }
        @Suppress("UNCHECKED_CAST")
        return if (ContinuationInterceptor === key) this as E else null
    }
    // minusKey方法多態(tài)實(shí)現(xiàn)
    public override fun minusKey(key: CoroutineContext.Key<*>): CoroutineContext {
        @OptIn(ExperimentalStdlibApi::class)
        if (key is AbstractCoroutineContextKey<*, *>) {
            return if (key.isSubKey(this.key) && key.tryCast(this) != null) EmptyCoroutineContext else this
        }
        return if (ContinuationInterceptor === key) EmptyCoroutineContext else this
    }
}

三.CoroutineDispatcher

CoroutineDispatcher類繼承自AbstractCoroutineContextElement類,實(shí)現(xiàn)了ContinuationInterceptor接口,是協(xié)程調(diào)度器的基類,代碼如下:

public abstract class CoroutineDispatcher :
    AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
    // ContinuationInterceptor的多態(tài)實(shí)現(xiàn),調(diào)度器本質(zhì)上就是攔截器
    @ExperimentalStdlibApi
    public companion object Key : AbstractCoroutineContextKey<ContinuationInterceptor, CoroutineDispatcher>(
        ContinuationInterceptor,
        { it as? CoroutineDispatcher })
    // 用于判斷調(diào)度器是否要調(diào)用dispatch方法進(jìn)行調(diào)度,默認(rèn)為true
    public open fun isDispatchNeeded(context: CoroutineContext): Boolean = true
    // 調(diào)度的核心方法,在這里進(jìn)行調(diào)度,執(zhí)行block
    public abstract fun dispatch(context: CoroutineContext, block: Runnable)
    // 如果調(diào)度是由Yield方法觸發(fā)的,默認(rèn)通過dispatch方法實(shí)現(xiàn)
    @InternalCoroutinesApi
    public open fun dispatchYield(context: CoroutineContext, block: Runnable): Unit = dispatch(context, block)
    // ContinuationInterceptor接口的方法,將續(xù)體包裹成DispatchedContinuation,并傳入當(dāng)前調(diào)度器
    public final override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
        DispatchedContinuation(this, continuation)
    // 釋放父協(xié)程與子協(xié)程的關(guān)聯(lián)。
    @InternalCoroutinesApi
    public override fun releaseInterceptedContinuation(continuation: Continuation<*>) {
        (continuation as DispatchedContinuation<*>).reusableCancellableContinuation?.detachChild()
    }
    // 重載了"+"操作,直接返回others
    // 因?yàn)閮蓚€(gè)調(diào)度器相加沒有意義,同一個(gè)上下文中只能有一個(gè)調(diào)度器
    // 如果需要加的是調(diào)度器對(duì)象,則直接替換成最新的,因此直接返回
    public operator fun plus(other: CoroutineDispatcher): CoroutineDispatcher = other
    override fun toString(): String = "$classSimpleName@$hexAddress"
}

四.EventLoop

EventLoop類繼承自CoroutineDispatcher類,用于協(xié)程中任務(wù)的分發(fā)執(zhí)行,只在runBlocking方法中和Dispatchers.Unconfined調(diào)度器中使用。與Handler中的Looper類似,在創(chuàng)建后會(huì)存儲(chǔ)在當(dāng)前線程的ThreadLocal中。EventLoop本身不支持延時(shí)執(zhí)行任務(wù),如果需要可以自行繼承EventLoop并實(shí)現(xiàn)Delay接口,EventLoop中預(yù)留了一部分變量和方法用于延時(shí)需求的擴(kuò)展。

為什么協(xié)程需要EventLoop呢?協(xié)程的本質(zhì)是續(xù)體傳遞,而續(xù)體傳遞的本質(zhì)是回調(diào),假設(shè)在Dispatchers.Unconfined調(diào)度下,要連續(xù)執(zhí)行多個(gè)suspend方法,就會(huì)有多個(gè)續(xù)體傳遞,假設(shè)suspend方法達(dá)到一定數(shù)量后,就會(huì)造成StackOverflow,進(jìn)而引起崩潰。同樣的,我們知道調(diào)用runBlocking會(huì)阻塞當(dāng)前線程,而runBlocking阻塞的原理就是執(zhí)行“死循環(huán)”,因此需要在循環(huán)中做任務(wù)的分發(fā),去執(zhí)行內(nèi)部協(xié)程在Dispatchers.Unconfined調(diào)度器下加入的任務(wù)。

EventLoop代碼如下:

internal abstract class EventLoop : CoroutineDispatcher() {
    // 用于記錄使用當(dāng)前EventLoop的runBlocking方法和Dispatchers.Unconfined調(diào)度器的數(shù)量
    private var useCount = 0L
    // 表示當(dāng)前的EventLoop是否被暴露給其他的線程
    // runBlocking會(huì)將EventLoop暴露給其他線程
    // 因此,當(dāng)runBlocking使用時(shí),shared必須為true
    private var shared = false
    // Dispatchers.Unconfined調(diào)度器的任務(wù)執(zhí)行隊(duì)列
    private var unconfinedQueue: ArrayQueue<DispatchedTask<*>>? = null
    // 處理任務(wù)隊(duì)列的下一個(gè)任務(wù),該方法只能在EventLoop所在的線程調(diào)用
    // 返回值<=0,說明立刻執(zhí)行下一個(gè)任務(wù)
    // 返回值>0,說明等待這段時(shí)間后,執(zhí)行下一個(gè)任務(wù)
    // 返回值為Long.MAX_VALUE,說明隊(duì)列里沒有任務(wù)了 
    public open fun processNextEvent(): Long {
        if (!processUnconfinedEvent()) return Long.MAX_VALUE
        return 0
    }
    // 隊(duì)列是否為空
    protected open val isEmpty: Boolean get() = isUnconfinedQueueEmpty
    // 下一個(gè)任務(wù)多長時(shí)間后執(zhí)行
    protected open val nextTime: Long
        get() {
            val queue = unconfinedQueue ?: return Long.MAX_VALUE
            return if (queue.isEmpty) Long.MAX_VALUE else 0L
        }
    // 任務(wù)的核心處理方法
    public fun processUnconfinedEvent(): Boolean {
        // 若隊(duì)列為空,則返回
        val queue = unconfinedQueue ?: return false
        // 從隊(duì)首取出一個(gè)任務(wù),如果為空,則返回
        val task = queue.removeFirstOrNull() ?: return false
        // 執(zhí)行
        task.run()
        return true
    }
    // 表示當(dāng)前EventLoop是否可以在協(xié)程上下文中被調(diào)用
    // EventLoop本質(zhì)上也是協(xié)程上下文
    // 如果EventLoop在runBlocking方法中使用,必須返回true
    public open fun shouldBeProcessedFromContext(): Boolean = false
    // 向隊(duì)列中添加一個(gè)任務(wù)
    public fun dispatchUnconfined(task: DispatchedTask<*>) {
        // 若隊(duì)列為空,則創(chuàng)建一個(gè)新的隊(duì)列
        val queue = unconfinedQueue ?:
            ArrayQueue<DispatchedTask<*>>().also { unconfinedQueue = it }
        queue.addLast(task)
    }
    // EventLoop當(dāng)前是否還在被使用
    public val isActive: Boolean
        get() = useCount > 0
    // EventLoop當(dāng)前是否還在被Unconfined調(diào)度器使用
    public val isUnconfinedLoopActive: Boolean
        get() = useCount >= delta(unconfined = true)
    // 判斷隊(duì)列是否為空
    public val isUnconfinedQueueEmpty: Boolean
        get() = unconfinedQueue?.isEmpty ?: true
    // 下面三個(gè)方法用于計(jì)算使用當(dāng)前的EventLoop的runBlocking方法和Unconfined調(diào)度器的數(shù)量
    // useCount是一個(gè)64位的數(shù),
    // 它的高32位用于記錄Unconfined調(diào)度器的數(shù)量,低32位用于記錄runBlocking方法的數(shù)量
    private fun delta(unconfined: Boolean) =
        if (unconfined) (1L shl 32) else 1L
    fun incrementUseCount(unconfined: Boolean = false) {
        useCount += delta(unconfined)
        // runBlocking中使用,shared為true
        if (!unconfined) shared = true 
    }
    fun decrementUseCount(unconfined: Boolean = false) {
        useCount -= delta(unconfined)
        // 如果EventLoop還在被使用
        if (useCount > 0) return
        assert { useCount == 0L }
        // 如果EventLoop不被使用了,并且在EventLoop中使用過
        if (shared) {
            // 關(guān)閉相關(guān)資源,并在ThreadLocal中移除
            shutdown()
        }
    }
    protected open fun shutdown() {}
}

協(xié)程中提供了EventLoopImplBase類,間接繼承自EventLoop,實(shí)現(xiàn)了Delay接口,用來延時(shí)執(zhí)行任務(wù)。同時(shí),協(xié)程中還提供單例對(duì)象ThreadLocalEventLoop用于EventLoop在ThreadLocal中的存儲(chǔ)。

到此這篇關(guān)于Kotlin圖文并茂講解續(xù)體與續(xù)體攔截器和調(diào)度器的文章就介紹到這了,更多相關(guān)Kotlin續(xù)體內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • AndroidQ分區(qū)存儲(chǔ)權(quán)限變更及適配的實(shí)現(xiàn)

    AndroidQ分區(qū)存儲(chǔ)權(quán)限變更及適配的實(shí)現(xiàn)

    這篇文章主要介紹了AndroidQ分區(qū)存儲(chǔ)權(quán)限變更及適配的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Android學(xué)習(xí)筆記——Menu介紹(一)

    Android學(xué)習(xí)筆記——Menu介紹(一)

    Android3.0(API level 11)開始,Android設(shè)備不再需要專門的菜單鍵。隨著這種變化,Android app應(yīng)該取消對(duì)傳統(tǒng)6項(xiàng)菜單的依賴。取而代之的是提供anction bar來提供基本的用戶功能
    2014-10-10
  • Android 判斷當(dāng)前網(wǎng)絡(luò)是否可用簡單實(shí)例

    Android 判斷當(dāng)前網(wǎng)絡(luò)是否可用簡單實(shí)例

    這篇文章主要介紹了Android 判斷當(dāng)前網(wǎng)絡(luò)是否可用簡單實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Android圓角設(shè)置方法看著一篇文章就夠了

    Android圓角設(shè)置方法看著一篇文章就夠了

    我們?cè)趯?shí)際工作中,android經(jīng)常有需要實(shí)現(xiàn)圓角的場(chǎng)景,下面這篇文章主要給大家介紹了關(guān)于Android圓角設(shè)置方法的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì)需要的朋友可以參考下
    2023-02-02
  • Android 修改系統(tǒng)關(guān)機(jī)動(dòng)畫的實(shí)現(xiàn)

    Android 修改系統(tǒng)關(guān)機(jī)動(dòng)畫的實(shí)現(xiàn)

    這篇文章主要介紹了Android 修改系統(tǒng)關(guān)機(jī)動(dòng)畫的實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Android Gradle Build Error:Some file crunching failed, see logs for details解決辦法

    Android Gradle Build Error:Some file crunching failed, see l

    這篇文章主要介紹了Android Gradle Build Error:Some file crunching failed, see logs for details解決辦法的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • Android入門教程之Vibrator(振動(dòng)器)

    Android入門教程之Vibrator(振動(dòng)器)

    本節(jié)我們介紹的是Vibrator(振動(dòng)器),是手機(jī)自帶的振動(dòng)器,其實(shí)就是Android給我們提供的用于機(jī)身震動(dòng)的一個(gè)服務(wù)!當(dāng)收到推送消息的時(shí)候我們可以設(shè)置震動(dòng)提醒。
    2016-07-07
  • Android事件處理的兩種方式詳解

    Android事件處理的兩種方式詳解

    事件是一種有用來收集用戶與應(yīng)用程序互動(dòng)數(shù)據(jù)的互動(dòng)組件,如按鍵或觸摸屏等放置事件,因?yàn)槊總€(gè)事件從Android框架維護(hù)事件隊(duì)列先入先出(FIFO)基礎(chǔ)上的隊(duì)列??梢栽诔绦蛑胁东@這些事件,按要求并采取適當(dāng)?shù)膭?dòng)作
    2023-02-02
  • Android簽名機(jī)制介紹:生成keystore、簽名、查看簽名信息等方法

    Android簽名機(jī)制介紹:生成keystore、簽名、查看簽名信息等方法

    這篇文章主要介紹了Android簽名機(jī)制介紹:生成keystore、簽名、查看簽名信息等方法,本文講解了升級(jí)App、權(quán)限檢查、生成keystore、對(duì)apk進(jìn)行簽名、查看簽名信息等內(nèi)容,需要的朋友可以參考下
    2015-04-04
  • Android編程實(shí)現(xiàn)設(shè)置按鈕背景透明與半透明及圖片背景透明的方法

    Android編程實(shí)現(xiàn)設(shè)置按鈕背景透明與半透明及圖片背景透明的方法

    這篇文章主要介紹了Android編程實(shí)現(xiàn)設(shè)置按鈕背景透明與半透明及圖片背景透明的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Button及ImageButton的背景屬性設(shè)置技巧,非常簡單實(shí)用,需要的朋友可以參考下
    2015-12-12

最新評(píng)論

漯河市| 陆川县| 开封市| 东乌珠穆沁旗| 宁安市| 元朗区| 东丰县| 宁明县| 永宁县| 云龙县| 密云县| 大丰市| 郸城县| 永平县| 介休市| 平山县| 禹城市| 榆林市| 红桥区| 新乡县| 宁波市| 稷山县| 巩义市| 梅河口市| 鹤庆县| 蓝山县| 永州市| 望谟县| 布尔津县| 阿拉尔市| 吴江市| 昭通市| 台安县| 丽水市| 宁国市| 汤阴县| 沙河市| 斗六市| 鞍山市| 福建省| 湖北省|