Dispatcher IO 和 Default 用法的区别
Difference between usage of Dispatcher IO and Default
本题中:
我们可以理解在 CPU 过程中使用 Dispatcher.Default
,例如 image/video 转换和 Dispatcher.IO
当 writing/reading 文件或 API 连接时。
但是在 class Dispatcher.kt
文档中,对于 IO
你会发现:
* This dispatcher shares threads with a [Default][Dispatchers.Default] dispatcher, so using
* `withContext(Dispatchers.IO) { ... }` does not lead to an actual switching to another thread —
* typically execution continues in the same thread.
所以基本上他们 运行 在同一个线程上。是真的有区别还是最后一个个用都无所谓?
谢谢!
不同之处在于 Dispatchers.Default
受限于 CPU 个核心的数量(最少为 2 个),因此只有 N 个(其中 N == cpu 个核心)任务可以运行 在此调度程序中并行。
在 IO 调度程序上,默认情况下有 64 个线程,因此在该调度程序上最多可以有 64 个并行任务 运行ning。
想法是 IO 调度程序花费大量时间等待(IO 阻塞),而默认调度程序用于 CPU 密集型任务,其中很少或没有睡眠。
So basically they run on the same thread anyway. There is a real difference or in the end it won't matter each one to use?
你引用的文档只是详细介绍了 Kotlin 引入的优化:在 Default
和 IO
之间切换上下文时,你不需要为切换到另一个线程而付出昂贵的代价;相反,线程本身移动到另一个池。
这不会影响 Default
和 IO
调度程序后面的线程池的整体属性:
Default
将固定大小硬编码为可用处理器的数量,因为这对 CPU 密集型任务有意义。
IO
是一个具有可配置最大大小的弹性线程池。此池中的线程预计大部分时间都处于不可运行状态,等待 IO 操作的完成,因此拥有比 CPU 个核心更多的线程是有意义的。
/**
* works on the thread on which it was invoked, for example if invoked from
* the main thread with GlobalScope, it will print main thread as thread name
*/
launch { // context of the parent, main runBlocking coroutine
println("main runBlocking : running thread: ${Thread.currentThread().name}")
}
/**
* this coroutine will not be confined to one single thread. If you want to print 1, 2, 3
* inside an Unconfined coroutine, the sequence might not be the same every time. as multiple
* thread could execute this single co-routine.
*/
launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
println("Unconfined : I'm working in thread ${Thread.currentThread().name}")
}
/** will work on default dispatcher thread. off the main thread.
* optimized for heavy operation like sorting, json parsing etc
* */
launch(Dispatchers.Default) { // will get dispatched to DefaultDispatcher
println("Default : I'm working in thread ${Thread.currentThread().name}")
}
/** start a coroutine with your own thread by its name.
* all the code will execute on this specified thread.
* */
launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}")
}
本题中:Dispatcher.Default
,例如 image/video 转换和 Dispatcher.IO
当 writing/reading 文件或 API 连接时。
但是在 class Dispatcher.kt
文档中,对于 IO
你会发现:
* This dispatcher shares threads with a [Default][Dispatchers.Default] dispatcher, so using
* `withContext(Dispatchers.IO) { ... }` does not lead to an actual switching to another thread —
* typically execution continues in the same thread.
所以基本上他们 运行 在同一个线程上。是真的有区别还是最后一个个用都无所谓?
谢谢!
不同之处在于 Dispatchers.Default
受限于 CPU 个核心的数量(最少为 2 个),因此只有 N 个(其中 N == cpu 个核心)任务可以运行 在此调度程序中并行。
在 IO 调度程序上,默认情况下有 64 个线程,因此在该调度程序上最多可以有 64 个并行任务 运行ning。
想法是 IO 调度程序花费大量时间等待(IO 阻塞),而默认调度程序用于 CPU 密集型任务,其中很少或没有睡眠。
So basically they run on the same thread anyway. There is a real difference or in the end it won't matter each one to use?
你引用的文档只是详细介绍了 Kotlin 引入的优化:在 Default
和 IO
之间切换上下文时,你不需要为切换到另一个线程而付出昂贵的代价;相反,线程本身移动到另一个池。
这不会影响 Default
和 IO
调度程序后面的线程池的整体属性:
Default
将固定大小硬编码为可用处理器的数量,因为这对 CPU 密集型任务有意义。IO
是一个具有可配置最大大小的弹性线程池。此池中的线程预计大部分时间都处于不可运行状态,等待 IO 操作的完成,因此拥有比 CPU 个核心更多的线程是有意义的。
/**
* works on the thread on which it was invoked, for example if invoked from
* the main thread with GlobalScope, it will print main thread as thread name
*/
launch { // context of the parent, main runBlocking coroutine
println("main runBlocking : running thread: ${Thread.currentThread().name}")
}
/**
* this coroutine will not be confined to one single thread. If you want to print 1, 2, 3
* inside an Unconfined coroutine, the sequence might not be the same every time. as multiple
* thread could execute this single co-routine.
*/
launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
println("Unconfined : I'm working in thread ${Thread.currentThread().name}")
}
/** will work on default dispatcher thread. off the main thread.
* optimized for heavy operation like sorting, json parsing etc
* */
launch(Dispatchers.Default) { // will get dispatched to DefaultDispatcher
println("Default : I'm working in thread ${Thread.currentThread().name}")
}
/** start a coroutine with your own thread by its name.
* all the code will execute on this specified thread.
* */
launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}")
}