Kotlin Coroutine launch{} 与 launch{ withContext{} }
Kotlin Coroutine launch{} vs launch{ withContext{} }
我的 Android 应用程序需要在后台(在服务内)做一些文件 read/write,首先我使用:
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
可以在需要时创建线程从而永远不会被阻塞,那么第一个代码不会有任何问题,对吧?
看来 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
使用协程范围上下文,但您可以像我上面那样更改它或使用 withContext
.
So basically most Coroutine only has 1 thread, if it is blocked, that coroutine will have no thread to do other job.
Dispatchers.IO
实际上默认为 64 个线程。
是的,这是一个带有警告的错误。 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()
}
另外,您的声明:
So basically most Coroutine only has 1 thread, if it is blocked, that coroutine will have no thread to do other job.
具有误导性。协程没有线程,Dispatcher 有。还有一些 Dispatcher 有很多线程。
我的 Android 应用程序需要在后台(在服务内)做一些文件 read/write,首先我使用:
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 仍然显示警告。
我不明白的是,withContext
在 Dispatchers.IO
上仍然是 运行。从 launch
块来看,它可能看起来像非阻塞,但如果 Dispatchers.IO
只有 1 个线程并且 withContext
块在该线程上是 运行,那么该线程是还是被屏蔽了是吧?
我还了解到 Dispatchers.IO
实际上有无限线程,它只是在需要时创建一个新线程。所以 withContext
实际上没有阻塞,但如果这是真的,为什么我们需要 withContext
块?如果 Dispatchers.IO
可以在需要时创建线程从而永远不会被阻塞,那么第一个代码不会有任何问题,对吧?
看来 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
使用协程范围上下文,但您可以像我上面那样更改它或使用 withContext
.
So basically most Coroutine only has 1 thread, if it is blocked, that coroutine will have no thread to do other job.
Dispatchers.IO
实际上默认为 64 个线程。
是的,这是一个带有警告的错误。 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()
}
另外,您的声明:
So basically most Coroutine only has 1 thread, if it is blocked, that coroutine will have no thread to do other job.
具有误导性。协程没有线程,Dispatcher 有。还有一些 Dispatcher 有很多线程。