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 引入的优化:在 DefaultIO 之间切换上下文时,你不需要为切换到另一个线程而付出昂贵的代价;相反,线程本身移动到另一个池。

这不会影响 DefaultIO 调度程序后面的线程池的整体属性:

  • 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}")
    }