欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Kotlin Channel處理多個數(shù)據(jù)組合的流

 更新時間:2022年11月25日 16:48:58   作者:wayne214  
最近項目中對 kotlin 的使用比較多。不得不說 kotlin 確實可以極大的提高 android 的開發(fā)效率,channel用于協(xié)程之間的通訊,使用send和receive往通道里寫入或者讀取數(shù)據(jù),2個方法為非阻塞掛起函數(shù),channel是熱流,不管有沒有訂閱者都會發(fā)送

結(jié)論先行

Kotlin協(xié)程中的Channel用于處理多個數(shù)據(jù)組合的流,隨用隨取,時刻準備著,就像自來水一樣,打開開關(guān)就有水了。

Channel使用示例

fun main() = runBlocking {
    logX("開始")
    val channel = Channel<Int> {  }
    launch {
        (1..3).forEach{
            channel.send(it)
            logX("發(fā)送數(shù)據(jù): $it")
        }
        // 關(guān)閉channel, 節(jié)省資源
        channel.close()
    }
    launch {
        for (i in channel){
            logX("接收數(shù)據(jù): $i")
        }
    }
    logX("結(jié)束")
}

示例代碼 使用Channel創(chuàng)建了一組int類型的數(shù)據(jù)流,通過send發(fā)送數(shù)據(jù),并通過for循環(huán)取出channel中的數(shù)據(jù),最后channel是一種協(xié)程資源,使用結(jié)束后應該及時調(diào)用close方法關(guān)閉,以免浪費不必要的資源。

Channel的源碼

public fun <E> Channel(
    capacity: Int = RENDEZVOUS,
    onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND,
    onUndeliveredElement: ((E) -> Unit)? = null
): Channel<E> =
    when (capacity) {
        RENDEZVOUS -> {}
        CONFLATED -> {}
        UNLIMITED -> {}
        else -> {}
    }

可以看到Channel的構(gòu)造函數(shù)包含了三個參數(shù),分別是capacity、onBufferOverflow、onUndeliveredElement.

首先看capacity,這個參數(shù)代表了管道的容量,默認參數(shù)是RENDEZVOUS,取值是0,還有其他一些值:

  • UNLIMITED: Int = Int.MAX_VALUE,沒有限量
  • CONFLATED: 容量為1,新的覆蓋舊的值
  • BUFFERED: 添加緩沖容量,默認值是64,可以通過修改VM參數(shù):kotlinx.coroutines.channels.defaultBuffer,進行修改

接下來看onBufferOverflow, 顧名思義就是管道容量滿了,怎么辦?默認是掛起,也就是suspend,一共有三種分別是:

SUSPNED、DROP_OLDEST以及DROP_LATEST

public enum class BufferOverflow {
    /**
     * Suspend on buffer overflow.
     */
    SUSPEND,
    /**
     * Drop **the oldest** value in the buffer on overflow, add the new value to the buffer, do not suspend.
     */
    DROP_OLDEST,
    /**
     * Drop **the latest** value that is being added to the buffer right now on buffer overflow
     * (so that buffer contents stay the same), do not suspend.
     */
    DROP_LATEST
}
  • SUSPEND,當管道的容量滿了以后,如果發(fā)送方還要繼續(xù)發(fā)送,我們就會掛起當前的 send() 方法。由于它是一個掛起函數(shù),所以我們可以以非阻塞的方式,將發(fā)送方的執(zhí)行流程掛起,等管道中有了空閑位置以后再恢復,有點像生產(chǎn)者-消費者模型
  • DROP_OLDEST,顧名思義,就是丟棄最舊的那條數(shù)據(jù),然后發(fā)送新的數(shù)據(jù),有點像LRU算法。
  • DROP_LATEST,丟棄最新的那條數(shù)據(jù)。這里要注意,這個動作的含義是丟棄當前正準備發(fā)送的那條數(shù)據(jù),而管道中的內(nèi)容將維持不變。

最后一個參數(shù)是onUndeliveredElement,從名字看像是沒有投遞成功的回調(diào),也確實如此,當管道中某些數(shù)據(jù)沒有成功接收時,這個就會被調(diào)用。

綜合這個參數(shù)使用一下

fun main() = runBlocking {
    println("開始")
    val channel = Channel<Int>(capacity = 2, onBufferOverflow = BufferOverflow.DROP_OLDEST) {
        println("onUndeliveredElement = $it")
    }
    launch {
        (1..3).forEach{
            channel.send(it)
            println("發(fā)送數(shù)據(jù): $it")
        }
        // 關(guān)閉channel, 節(jié)省資源
        channel.close()
    }
    launch {
        for (i in channel){
            println("接收數(shù)據(jù): $i")
        }
    }
    println("結(jié)束")
}

輸出結(jié)果如下:
開始
結(jié)束
發(fā)送數(shù)據(jù): 1
發(fā)送數(shù)據(jù): 2
發(fā)送數(shù)據(jù): 3
接收數(shù)據(jù): 2
接收數(shù)據(jù): 3

安全的從Channel中取數(shù)據(jù)

先看一個例子

val channel: ReceiveChannel<Int> = produce {
        (1..100).forEach{
            send(it)
            println("發(fā)送: $it")
        }
    }
while (!channel.isClosedForReceive){
    val i = channel.receive();
    println("接收: $i")
}

輸出報錯信息:
Exception in thread "main" kotlinx.coroutines.channels.ClosedReceiveChannelException: Channel was closed

可以看到使用isClosedForReceive判斷是否關(guān)閉再使用receive方法接收數(shù)據(jù),依然會報錯,所以不推薦使用這種方式。

推薦使用上面for循環(huán)的方式取數(shù)據(jù),還有kotlin推薦的consumeEach方式,看一下示例代碼

val channel: ReceiveChannel<Int> = produce {
        (1..100).forEach{
            send(it)
            println("發(fā)送: $it")
        }
    }
channel.consumeEach {
    println("接收:$it")
}

所以,當我們想要獲取Channel當中的數(shù)據(jù)時,我們盡量使用 for 循環(huán),或者是channel.consumeEach {},不要直接調(diào)用channel.receive()。

熱的數(shù)據(jù)流從何而來

先看一下代碼

    println("開始")
    val channel = Channel<Int>(capacity = 3, onBufferOverflow = BufferOverflow.DROP_OLDEST) {
        println("onUndeliveredElement = $it")
    }
    launch {
        (1..3).forEach{
            channel.send(it)
            println("發(fā)送數(shù)據(jù): $it")
        }
    }
    println("結(jié)束")
}

輸出:
開始
結(jié)束
發(fā)送數(shù)據(jù): 1
發(fā)送數(shù)據(jù): 2
發(fā)送數(shù)據(jù): 3

可以看到上述代碼中并沒有 取channel中的數(shù)據(jù),但是發(fā)送的代碼正常執(zhí)行了,這種“不管有沒有接收方,發(fā)送方都會工作”的模式,就是我們將其認定為“熱”的原因。

舉個例子,就像去海底撈吃火鍋一樣,你不需要主動要求服務員加水,服務員看到你的杯子中水少了,會自動給你添加,你只管拿起水杯喝水就行了。

總的來說,不管接收方是否存在,Channel 的發(fā)送方一定會工作。

Channel能力的來源

通過源碼可以看到Channel只是一個接口,它的能力來源于SendChannel和ReceiveChannel,一個發(fā)送管道,一個接收管道,相當于做了一個組合。

這也是一種良好的設計思想,“對讀取開放,對寫入封閉”的開閉原則。

到此這篇關(guān)于Kotlin Channel處理多個數(shù)據(jù)組合的流的文章就介紹到這了,更多相關(guān)Kotlin Channel內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android實現(xiàn)選項菜單子菜單

    Android實現(xiàn)選項菜單子菜單

    這篇文章主要為大家詳細介紹了Android實現(xiàn)選項菜單子菜單,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • Android開發(fā)Kotlin語言協(xié)程中的并發(fā)問題和互斥鎖

    Android開發(fā)Kotlin語言協(xié)程中的并發(fā)問題和互斥鎖

    Android開發(fā)Kotlin語言提供了多種機制來處理并發(fā)和同步,其中包括高層次和低層次的工具,對于常規(guī)的并發(fā)任務,可以利用 Kotlin 協(xié)程提供的結(jié)構(gòu)化并發(fā)方式,而對于需要更低層次的鎖定機制,可以使用Mutex(互斥鎖)來實現(xiàn)對共享資源的線程安全訪問
    2024-06-06
  • android查看網(wǎng)絡圖片的實現(xiàn)方法

    android查看網(wǎng)絡圖片的實現(xiàn)方法

    這篇文章主要為大家詳細介紹了android查看網(wǎng)絡圖片的實現(xiàn)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • Android自定義View實現(xiàn)鐘擺效果進度條PendulumView

    Android自定義View實現(xiàn)鐘擺效果進度條PendulumView

    這篇文章主要介紹了Android自定義View實現(xiàn)鐘擺效果進度條PendulumView,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • php 異步調(diào)用方法實現(xiàn)示例

    php 異步調(diào)用方法實現(xiàn)示例

    客戶端與服務器端是通過HTTP協(xié)議進行連接通訊,客戶端發(fā)起請求,服務器端接收到請求后執(zhí)行處理,并返回處理結(jié)果
    2014-01-01
  • Kotlin中單例模式和Java的對比淺析

    Kotlin中單例模式和Java的對比淺析

    目前java中的單例模式有多種寫法,kotlin中的寫法更多一點,下面這篇文章主要給大家介紹了關(guān)于Kotlin中單例模式和Java對比的相關(guān)資料,會總結(jié)全部的到單例模式寫法,需要的朋友可以參考下
    2018-07-07
  • AndroidStudio中重載方法@Override的使用詳解

    AndroidStudio中重載方法@Override的使用詳解

    這篇文章主要介紹了AndroidStudio中重載方法@Override的使用詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • android判斷phonegap是否聯(lián)網(wǎng)且加載super.loadUrl網(wǎng)址

    android判斷phonegap是否聯(lián)網(wǎng)且加載super.loadUrl網(wǎng)址

    android判斷phonegap是否聯(lián)網(wǎng)動態(tài)加載super.loadUrl網(wǎng)址,接下來本文所提供的知識會幫助你解決以上問題,感興趣的你可不要錯過了哈
    2013-02-02
  • 深入淺出學習Android ListView基礎

    深入淺出學習Android ListView基礎

    這篇文章主要介紹了深入淺出的帶領(lǐng)大家學習Android ListView基礎,ListView是安卓里常用的控件,本文介紹一下常用用法,以及優(yōu)化等方法,感興趣的小伙伴們可以參考一下
    2016-01-01
  • Flutter繪圖組件之CustomPaint使用詳解

    Flutter繪圖組件之CustomPaint使用詳解

    CustomPaint是Flutter中用于自由繪制的一個widget,它與android原生的繪制規(guī)則基本一致,以當前Canves(畫布)的左上角為原點進行繪制。本文將詳細講解CustomPaint的使用教程,需要的可以參考一下
    2022-03-03

最新評論