暂停Kotlin'中的IO绑定和CPU绑定函数;s合作项目

暂停Kotlin'中的IO绑定和CPU绑定函数;s合作项目,kotlin,kotlin-coroutines,Kotlin,Kotlin Coroutines,在协同程序中执行一个IO绑定函数(比如,从后端请求数据)可以让我在请求结果可用之前暂停它的执行,对吗?然而,一个CPU绑定的函数(例如解析一个巨大的文本文件)并不“等待”任何东西,它只是做了大量的工作。那么,在一个协同程序中执行它不会给我暂停执行的优势吗?当涉及到CPU绑定函数时,协程给我的唯一(有价值的)优势是能够选择在执行函数时将被阻塞的线程(或线程池),对吗 那么,在一个协同程序中执行它不会给我暂停执行的优势吗 我不确定我是否理解您的意思,但是调用挂起函数将挂起调用的协同路由,不管您选择什

在协同程序中执行一个IO绑定函数(比如,从后端请求数据)可以让我在请求结果可用之前暂停它的执行,对吗?然而,一个CPU绑定的函数(例如解析一个巨大的文本文件)并不“等待”任何东西,它只是做了大量的工作。那么,在一个协同程序中执行它不会给我暂停执行的优势吗?当涉及到CPU绑定函数时,协程给我的唯一(有价值的)优势是能够选择在执行函数时将被阻塞的线程(或线程池),对吗

那么,在一个协同程序中执行它不会给我暂停执行的优势吗

我不确定我是否理解您的意思,但是调用挂起函数将挂起调用的协同路由,不管您选择什么调度程序,而这并不取决于据我所知的函数内部的内容

但是,请注意,从协程内部调用阻塞函数将使该协程阻塞执行它的线程,这里没有魔法。这就是为什么应该避免在协程内部执行阻塞操作

当涉及到CPU绑定函数时,协程给我的唯一(有价值的)优势是能够选择在执行函数时将被阻塞的线程(或线程池),对吗

使用
Dispatchers.IO
Dispatchers.Default
仅具有选择不同线程池的效果,是的

IO
的情况下,池将根据需要生成尽可能多的线程,因为它们都可以“在I/O上被阻塞”


对于
默认值
,只会创建与内核数量成比例的线程数量,因为受CPU限制的任务没有必要创建比内核更多的线程(如果所有内核都很忙,那么上下文切换只会降低整体性能).

挂起函数不会自动将函数设置为不阻塞线程,就像下面的情况一样,因为它仍然会阻塞调用线程(与用于启动协同路由的作用域关联的调度程序)

通过使用withContext,可以将挂起函数设置为非阻塞线程函数,如下所示:

suspend fun findBigPrime(): BigInteger =
    withContext(Dispatchers.Default) {
        BigInteger.probablePrime(4096, Random())
    }
这会导致从主/调用线程启动的协同路由被阻塞,而不是线程本身被阻塞


对不起,我的共事思维模式仍然很混乱,@Joffrey。如果我只是在CPU绑定函数的声明中写入'suspend',并在
启动(Dispatchers.Unconfined)
中调用它,我会得到什么好处?它与对IO绑定函数执行相同操作有什么不同吗?@bernardo.g我不是
Unconfined
dispatcher的专家,但除非您有非常具体的用例,否则不鼓励使用它。最后,它使协程在当前线程中启动,直到第一个挂起点,然后根据调用的挂起函数在可能不同的线程中恢复。这意味着您的协同程序的开始一定会立即执行。@bernardo.g然而,如果您做的第一件事是调用CPU绑定的挂起函数,这是一个挂起点,我想您的函数可能会在另一个线程中执行,但我不太清楚这一点。因此,在我看来,我不认为你在这里所描述的有任何“优势”,我也不认为用IO绑定的function这样做有什么区别,除了IO绑定的函数可能会阻塞它所调用的线程这一事实。
suspend fun findBigPrime(): BigInteger =
    withContext(Dispatchers.Default) {
        BigInteger.probablePrime(4096, Random())
    }