Multithreading 协同路由范围、暂停和与上下文查询
下面我有3个片段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
我试着读了这篇文章,但看不清楚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
}
}
}