Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 协同路由范围、暂停和与上下文查询_Multithreading_Kotlin_Coroutine_Kotlin Coroutines - Fatal编程技术网

Multithreading 协同路由范围、暂停和与上下文查询

Multithreading 协同路由范围、暂停和与上下文查询,multithreading,kotlin,coroutine,kotlin-coroutines,Multithreading,Kotlin,Coroutine,Kotlin Coroutines,下面我有3个片段 只是范围发射 范围启动与暂停 使用suspend和withContext启动作用域 我看到它们在与主线程不同的线程中启动,并且异步运行,不阻塞主线程 我想知道他们有什么不同?如果它们都一样,那么1是最好的。如果没有,我应该在什么时候使用2或3 我试着读了这篇文章,但看不清楚1和2是一样的。只有当函数与协同程序一起执行某些操作时,才必须向函数添加suspend修饰符 第一种和第三种情况之间的区别: fun main() = CoroutineScope(Dispatchers.I

下面我有3个片段

  • 只是范围发射
  • 范围启动与暂停
  • 使用suspend和withContext启动作用域
  • 我看到它们在与主线程不同的线程中启动,并且异步运行,不阻塞主线程

    我想知道他们有什么不同?如果它们都一样,那么1是最好的。如果没有,我应该在什么时候使用2或3


    我试着读了这篇文章,但看不清楚

    1和2是一样的。只有当函数与协同程序一起执行某些操作时,才必须向函数添加
    suspend
    修饰符

    第一种和第三种情况之间的区别:

    fun main() = CoroutineScope(Dispatchers.IO).launch { 
        // io thead executor
        runMe()
    }
    // still io thread executor
    fun rumMe() = doSomething()
    
    fun main() = CoroutineScope(Dispatchers.IO).launch { 
        // io thead executor
        runMe()
    }
    suspend fun rumMe() = withContext(Dispatchers.Default) { 
        // default/cpu thead executor
        doSomething()
    }
    

    通过向函数添加
    suspend
    修饰符,可以允许该函数使用其他挂起函数。例如,如果
    runMe()。请参阅文档部分

    挂起函数与普通函数的另一个主要区别是挂起函数。让我们看看Android示例:

    class MyViewModel : BaseViewModel() {
      init {
        viewModelScope.launch {
          val firstPart = loadFirstPartOfData()
          val secondPart = loadSecondPartOfData(firstPart)
          ...
        }
      }
    
      suspend loadFirstPartOfData() = withContext(Dispatchers.IO) { ... }
    
      suspend loadSecondPartOfData(firstPartOfData: FirstPartOfData) {
        // some UI thread safe calculations
        return withContext(Dispatchers.IO) {
            // network request here
        }
      }
    }
    
    假设视图(Android活动)加载数据以显示它。如果在加载第二部分数据之前关闭了活动,则加载第二部分数据是浪费时间的。但是,由于
    loadSecondPartOfData()
    函数处于挂起状态,因此它会检查作用域是否处于活动状态,如果作用域未处于活动状态,则不会执行该函数

    还要注意函数如何使用上下文(Dispatchers.IO)
    。这些函数是从
    viewModelScope.launch
    (默认情况下使用
    Dispatchers.Main
    (UI线程)调用的,但是从UI线程调用函数是安全的,因为执行上下文是由函数显式选择的。这是编写挂起函数的正确方法,因为调用函数时不必担心当前线程。关于你的第三个问题


    在您的示例中,第一个代码片段可以工作,但在实际应用程序中,情况会像往常一样变得稍微复杂一些。

    谢谢。我明白。但是如果我们只想在不同的线程中执行,那么1和3仍然没有什么不同,对吗?我的实验使用
    ${thread.currentThread()}
    打印线程,结果表明,对于案例3,在
    启动
    withContext
    中有相同的线程。是的,如果您不想使用主线程,那么使用第三个代码段是没有意义的。看起来像
    Dispatchers.IO
    Dispatchers.Default
    共享线程(在文件末尾),您可以将
    Dispatchers.Default
    更改为
    newSingleThreadContext(“test”)
    以查看
    ${Thread.currentThread()}
    只是为了澄清一下,该函数是可取消的,不是因为
    suspend
    关键字,而是因为使用了一些暂停函数,例如
    withContext
        fun main() = CoroutineScope(Dispatchers.IO).launch { runMe() }
        suspend fun rumMe() = withContext(Dispatchers.Default) { doSomething() }
    
    fun main() = CoroutineScope(Dispatchers.IO).launch { 
        // io thead executor
        runMe()
    }
    // still io thread executor
    fun rumMe() = doSomething()
    
    fun main() = CoroutineScope(Dispatchers.IO).launch { 
        // io thead executor
        runMe()
    }
    suspend fun rumMe() = withContext(Dispatchers.Default) { 
        // default/cpu thead executor
        doSomething()
    }
    
    class MyViewModel : BaseViewModel() {
      init {
        viewModelScope.launch {
          val firstPart = loadFirstPartOfData()
          val secondPart = loadSecondPartOfData(firstPart)
          ...
        }
      }
    
      suspend loadFirstPartOfData() = withContext(Dispatchers.IO) { ... }
    
      suspend loadSecondPartOfData(firstPartOfData: FirstPartOfData) {
        // some UI thread safe calculations
        return withContext(Dispatchers.IO) {
            // network request here
        }
      }
    }