簡體   English   中英

Kotlin 協程啟動{} vs 啟動{ withContext{} }

[英]Kotlin Coroutine launch{} vs launch{ withContext{} }

我的 Android 應用程序需要在后台(在服務內)進行一些文件讀/寫,首先我使用:

CoroutineScope(Dispatchers.IO).launch {
    val fos = openFileOutput(fileName, MODE_PRIVATE)
    val oos = ObjectOutputStream(fos)
    oos.writeObject(myObj)
    oos.close()
}

塊內的每一行都有一個警告:“不適當的阻塞方法調用”

搜索問題后,我認為我理解了 80%。 所以基本上大多數協程只有1個線程,如果它被阻塞,協程將沒有線程來做其他工作。 要解決這個問題,我們應該像這樣將它包裝在withContext

CoroutineScope(Dispatchers.IO).launch {
    withContext(Dispatchers.IO) {
        val fos = openFileOutput(fileName, MODE_PRIVATE)
        val oos = ObjectOutputStream(fos)
        oos.writeObject(myObj)
        oos.close()
    }
}

Android Studio 仍然顯示警告。 帖子說這只是 Android Studio 中的一個錯誤,這個解決方案很好。

我不明白的是, withContext仍在Dispatchers.IO上運行。 launch塊來看,它可能看起來像非阻塞,但如果Dispatchers.IO只有 1 個線程並且withContext塊在該線程上運行,那么該線程仍然被阻塞,不是嗎?

我還了解到Dispatchers.IO實際上有無限線程,它只是在需要時創建一個新線程。 所以withContext實際上並沒有阻塞,但如果這是真的,為什么我們需要withContext塊? 如果Dispatchers.IO可以在需要時創建線程從而永遠不會被阻塞,那么第一個代碼不會有任何問題,對吧?

是的,這是一個帶有警告的錯誤。 Lint 無法檢測到 scope 使用的是什么 Dispatcher,我想他們只是假設您使用的是 scope,其上下文使用Dispatchers.Main ,因為這是最常見的。

您的 CoroutineScope(偽)構造函數具有Dispatchers.IO的上下文,因此如果不修改它, launch會繼承該上下文,因此您啟動的協程也使用Dispatchers.IO 所以,你的withContext塊是多余的。

解決方法是在啟動時指定調度程序:

CoroutineScope(Job()).launch(Dispatchers.IO) {
    val fos = openFileOutput(fileName, MODE_PRIVATE)
    val oos = ObjectOutputStream(fos)
    oos.writeObject(myObj)
    oos.close()
}

另外,你的聲明:

所以基本上大多數協程只有1個線程,如果它被阻塞,協程將沒有線程來做其他工作。

具有誤導性。 協程沒有線程,而 Dispatcher 有。 並且有些 Dispatcher 有很多線程。

似乎 Android Studio 中確實存在錯誤。 以下代碼對我沒有顯示任何警告:

CoroutineScope(Dispatchers.IO).launch(Dispatchers.IO) {
    val fos = context.openFileOutput("", Context.MODE_PRIVATE)
    val oos = ObjectOutputStream(fos)
    oos.writeObject(myObj)
    oos.close()
}

您還應該知道,這段代碼與您共享的兩段代碼在行為上幾乎沒有區別。 在這三種情況下,代碼都將在 IO 線程上執行。

  • CoroutineScope(context)
  • launch(context)
  • withContext(context

所有這些方法都只是指定協程上下文。 默認情況下, launch使用協程 scope 上下文,但您可以像我上面所做的那樣或使用withContext來更改它。

所以基本上大多數協程只有1個線程,如果它被阻塞,協程將沒有線程來做其他工作。

Dispatchers.IO實際上默認為 64 個線程。

暫無
暫無

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

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