簡體   English   中英

從 coroutineScope 內部創建actor會阻塞線程,但是作為 CoroutineScope 的擴展 function 創建的相同actor不會

[英]Creating the actor from inside coroutineScope is blocking the thread, but the same actor created as extension function of CoroutineScope is not

我正在嘗試使用 kotlin 中的演員構建器構造。 我已經編寫了下面的代碼來發送和接收來自演員的消息。

package com.byteobject.prototype.kotlin

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.actor
import kotlinx.coroutines.channels.consumeEach

class GreetingsMessage(val to: String, val greetings: CompletableDeferred<String>)

fun CoroutineScope.newGreeter(greet: String) = actor<GreetingsMessage> {
        channel.consumeEach {
            it.greetings.complete("$greet ${it.to}")
        }
    }

fun main() {
    runBlocking {
        val greeter = newGreeter("Hello")
        val greetingsMessage = GreetingsMessage("World", CompletableDeferred())
        launch(Dispatchers.Default) {
            greeter.send(greetingsMessage)
        }
        launch(Dispatchers.Default) {
            println(greetingsMessage.greetings.await())
            greeter.close()
        }
    }
}

此代碼按預期工作。 但下面的代碼不是,因為它正在掛起程序。

package com.byteobject.prototype.kotlin

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.actor
import kotlinx.coroutines.channels.consumeEach

class GreetingsMessage(val to: String, val greetings: CompletableDeferred<String>)

suspend fun newGreeter(greet: String) = coroutineScope {
    actor<GreetingsMessage> {
        channel.consumeEach {
            it.greetings.complete("$greet ${it.to}")
        }
    }
}

fun main() {
    runBlocking {
        val greeter = newGreeter("Hello")
        val greetingsMessage = GreetingsMessage("World", CompletableDeferred())
        launch(Dispatchers.Default) {
            greeter.send(greetingsMessage)
        }
        launch(Dispatchers.Default) {
            println(greetingsMessage.greetings.await())
            greeter.close()
        }
    }
}

通過將 newGreeter function 設為掛起 function 並封閉 function 並通過 coroutineGreeter 方法將其掛起的新程序的調用,對代碼稍作修改。 我相信 newGreeter 作為 function 到 CoroutineScope 的擴展和作為包含在 coroutineScope 內的暫停 function 應該完全相同。

我想知道這兩種方法之間的區別以及為什么第二種方法會掛起程序。

我用生產 function 嘗試了同樣的事情,在這里我還發現了暫停 function 以獲取 ReceieveChannel 的調用正在阻塞線程,其中作為擴展 ZC1C425268E68385D14ZA94 使用的相同生產結構正在工作

這段代碼是非阻塞的

package com.byteobject.prototype.kotlin

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.produce
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun CoroutineScope.produceIntegers(n: Int) = produce<Int> {
        for (i in 1..n)
            send(i)
        close()
    }

fun main() {
    runBlocking {
        val intChan = produceIntegers(10)
        launch {
            for (i in intChan)
                println(i)
        }
    }
}

因為這阻塞了對produceIntegers方法的調用

package com.byteobject.prototype.kotlin

import kotlinx.coroutines.channels.produce
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

suspend fun produceIntegers(n: Int) = coroutineScope {
    produce<Int> {
        for (i in 1..n)
            send(i)
        close()
    }
}

fun main() {
    runBlocking {
        val intChan = produceIntegers(10)
        launch {
            for (i in intChan)
                println(i)
        }
    }
}

問題是coroutineScope { }創建了一個新的阻塞 scope(結構化並發) - 等待所有啟動的協程完成。

見: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.ZFC35FDC70D5FC69D2369EZ8

這個 function 在給定塊及其所有子協程完成后立即返回。

另一方面,擴展 function 只是使用上下文(接收器)中的協程范圍。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM