Android中协程的挂起函数由哪个组件执行?
谁负责执行Android中的挂起函数?
我的探究实验
我最近尝试探究到底是谁负责执行挂起函数,因此在协程中创建了一些自定义挂起函数,代码如下:
fun main(args: Array<String>) { for (x in 1..20){ CoroutineScope(Dispatchers.Default).launch{ for (i in 1..5) { if(i % 2 == 0){ myFun(i, Thread.currentThread().name) }else{ myFun2(i, Thread.currentThread().name) } } } } Thread.sleep(3000000) // 仅用于等待所有协程执行完成,可忽略 }
suspend fun myFun(n : Int, tName : String) { println("myFun method called from Thread = $tName, for i = $n") println("myFun -> executing on Thread = ${Thread.currentThread().name}, came from Thread = $tName") delay(1000) val x = n * n; println("myFun -> performing square operation on Thread = ${Thread.currentThread().name}, for i = $n came from Thread = $tName") myFun3(x, Thread.currentThread().name, tName); println("myFun method finished for i = $n, on Thread = ${Thread.currentThread().name} came from Thread = $tName") } suspend fun myFun2(n : Int, tName: String){ println("myFun2 method called from Thread = $tName, for i = $n") println("myFun2 -> executing on Thread = ${Thread.currentThread().name} came from Thread = $tName") delay(1000) val x = n * n * n; println("myFun2 -> performing cube operation on Thread = ${Thread.currentThread().name} for i = $n came from Thread = $tName") myFun3(x, Thread.currentThread().name, tName); println("myFun2 method finished for i = $n, on Thread = ${Thread.currentThread().name}, came from Thread = $tName") } suspend fun myFun3(n : Int, parentFunThread : String, cThread: String){ val fun3Thread = Thread.currentThread().name if(!fun3Thread.equals(parentFunThread) || !fun3Thread.equals(cThread) || !parentFunThread.equals(cThread)){ println("--------------------------------------------Found-------------------------") } println("myFun3 method called from Thread = $parentFunThread, for x = $n through coroutineThread = $cThread") println("myFun3 -> executing on Thread = $fun3Thread, came from Thread = $parentFunThread, coroutineThread = $cThread") println("myFun3 -> final value of x = $n onThread = $fun3Thread, came from Thread = $parentFunThread, coroutineThread = $cThread") println("myFun3 method finished for x = $n, on Thread = $fun3Thread, came from Thread = $parentFunThread, coroutineThread = $cThread") }
(注:原代码中myFun3未定义fun3Thread变量,此处补充定义以保证代码可运行)
实验发现
我发现自定义挂起函数的执行和普通函数类似,不会暂停当前协程、将协程与底层线程分离以释放线程给其他协程,始终在调用它的线程上执行;但当调用内置挂起函数delay(1000)时,底层线程会发生切换。
疑问
由于存在多种类型的挂起函数(如Retrofit的API调用方法、Room数据库查询函数、delay函数等),我想请教:在Android中,到底是哪个组件负责执行这些挂起函数?
解答
挂起函数的执行逻辑本质上由协程调度器(CoroutineDispatcher)和挂起函数的内部实现共同决定,具体可以拆解为以下几点:
自定义挂起函数:如果你的挂起函数内部没有调用真正触发协程挂起的API(比如
delay、IO操作),它就只是标记了suspend关键字的普通函数,会直接在调用它的协程所在线程上同步执行,不会触发线程切换——这就是你实验里自定义函数的表现。内置/框架提供的挂起函数:
- 像
delay这类Kotlin协程库内置的挂起函数,内部会借助Dispatchers.Default(或指定调度器)的线程池,在等待时间结束后,将协程的后续逻辑重新调度到可用线程上执行,所以会看到线程切换。 - Retrofit、Room这类框架的挂起函数,内部会将IO操作(网络请求、数据库查询)委托给专门的
Dispatchers.IO调度器执行,当IO操作完成后,再把协程切回合适的线程(比如Android主线程,若使用viewModelScope这类绑定主线程的作用域)。
- 像
简单来说:协程调度器是负责分配线程、调度协程执行的核心组件,而挂起函数是否触发线程切换,完全取决于它内部是否调用了让协程挂起并切换调度器的逻辑。没有挂起逻辑的suspend函数,和普通函数无本质区别,自然不会切换线程。
内容的提问来源于stack exchange,提问作者Roop Kishore
相关产品推荐
相关产品推荐

