Jef*_*hen 9 multithreading android kotlin kotlin-coroutines
我的 Android 应用程序需要在后台(在服务内)执行一些文件读/写操作,首先我使用:
CoroutineScope(Dispatchers.IO).launch {
val fos = openFileOutput(fileName, MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
Run Code Online (Sandbox Code Playgroud)
块内的每一行都有一个警告:“不适当的阻塞方法调用”
搜索完问题后,我想我明白了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()
}
}
Run Code Online (Sandbox Code Playgroud)
Android Studio 仍然显示警告。帖子说这只是Android Studio中的一个错误,这个解决方案很好。
我不明白的是,withContext
仍然在运行Dispatchers.IO
。从launch
块来看,它可能看起来像非阻塞,但如果Dispatchers.IO
只有 1 个线程并且withContext
块在该线程上运行,那么该线程仍然被阻塞,不是吗?
我还了解到Dispatchers.IO
实际上有无限的线程,它只是在需要时创建一个新线程。所以withContext
实际上并没有阻塞,但如果这是真的,为什么我们需要阻塞呢withContext
?如果可以在需要时创建线程,因此第一个代码不会有任何问题,Dispatchers.IO
因此永远不会被阻塞,对吗?
是的,这是一个带有警告的错误。Lint 无法检测范围正在使用什么 Dispatcher,我想他们只是假设您使用的范围的上下文使用 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()
}
Run Code Online (Sandbox Code Playgroud)
另外,你的声明:
所以基本上大多数协程只有 1 个线程,如果它被阻塞,那么该协程将没有线程去做其他工作。
具有误导性。协程没有线程,调度程序有。有些调度程序有很多线程。
看来Android Studio确实存在一个bug。以下代码对我没有显示任何警告:
CoroutineScope(Dispatchers.IO).launch(Dispatchers.IO) {
val fos = context.openFileOutput("", Context.MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
Run Code Online (Sandbox Code Playgroud)
您还应该知道,此代码与您共享的两个代码之间的行为实际上没有区别。在所有三种情况下,代码都将在 IO 线程上执行。
CoroutineScope(context)
launch(context)
withContext(context
所有这些方法都只是指定协程上下文。默认情况下launch
使用协程范围上下文,但您可以像我上面所做的那样或使用withContext
.
所以基本上大多数协程只有 1 个线程,如果它被阻塞,那么该协程将没有线程去做其他工作。
Dispatchers.IO
实际上默认为 64 个线程。
归档时间: |
|
查看次数: |
7573 次 |
最近记录: |