Kotlin Coroutine runBlocking、delay - chuwuwang/ReadingNote GitHub Wiki
GlobalScope.launch
GlobalScope.launch 函数可以创建一个协程的作用域,这样传递给 launch 函数的代码块(Lambda 表达式)就是在协程中运行的了。
GlobalScope.launch 函数每次创建的都是一个顶层协程,这种协程当应用程序运行结束时也会跟着一起结束。
launch
launch 函数和 GlobalScope.launch 函数是不同的。首先它必须在协程的作用域中才能调用,其次它会在当前协程的作用域下创建子协程。
子协程的特点是如果外层作用域的协程结束了,该作用域下的所有子协程也会一同结束。
相比而言,GlobalScope.launch 函数创建的永远是顶层协程,这一点和线程比较像,因为线程没有顶级这一说,永远都是顶层的。
coroutineScope
coroutineScope 函数和 runBlocking 函数还有点类似,它可以保证其作用域内的所有代码和子协程在全部执行完之前,会一直阻塞当前协程。
coroutineScope 只会阻塞当前协程,既不影响其他协程,也不影响任何线程,因此是不会造成任何性能问题的。而 runBlocking 函数由于会阻塞当前线程,如果恰好你在主线程中调用它的话,就有可能导致界面卡死的情况,所有不推荐在实际项目中使用它。
coroutineScope 只可以在协程作用域或者挂起函数中调用,而 launch 只能在协程作用域中调用。
delay
delay 函数可以让当前协程延迟指定时间后在运行,但它和 Thread.sleep()方法不同。delay 函数是一个非阻塞式的挂起函数,它只会挂起当前协程,并不会影响到其他协程的运行。而 Thread.sleep()方法会阻塞当前的线程,这样运行在该线程下的所有协程都会被阻塞。
注意:delay 函数只能在协程的作用域或者其他挂起函数中使用。
runBlocking
runBlocking 函数同样会创建一个协程的作用域,但是它可以保证在协程作用域内的所有代码和子协程没有全部执行完之前一直阻塞当前线程。
需要注意的是,runBlocking 函数通常只应该在测试环境下使用,在正式环境中使用容易产生一些性能的问题。
运行一个新的协程并且阻塞当前可中断的线程直至协程执行完成,该函数不应从一个协程中使用,该函数被设计用于桥接普通阻塞代码到以挂起风格(suspending style)编写的库,以用于主函数与测试。
这段话怎么理解呢?这要从 suspend 修饰符说起,协程使用中可以使用该修饰符修饰一个函数,表示该函数为挂起函数,从而运行在协程中。挂起函数,它不会造成线程阻塞,但是会挂起 协程,并且只能在协程中使用。挂起函数不可以在main函数中被调用,那么我们怎么调试呢?对了,就是使用 runBlocking 函数!
总结:runBlocking 方法,可以在普通的阻塞线程中开启一个新的协程以用于运行挂起函数,并且可以在协程中通过调用 launch 方法,开启一个子协程,用于运行后台阻塞任务。
runBlocking 启动的协程任务会阻断当前线程,直到该协程执行结束。当协程执行结束之后,页面才会被显示出来。
runBlocking 通常适用于单元测试的场景,而业务开发中不会用到这个函数。
runBocking 和 coroutineScope 区别
可以在全局创建协程的方法:runBocking 和 lauch。lauch 与 runBlocking都能在全局开启一个协程,但 lauch 是非阻塞的。而 runBlocking 是阻塞的。阻塞和非阻塞的意思是,当前运行的代码块是否会阻塞当前线程。
coroutineScope 函数又是怎么一回事呢?
官方文档中说了一段不是很容易理解的话:除了由不同的构建器提供协程作用域之外,还可以使用 coroutineScope 构建器声明自己的作用域。它会创建一个协程作用域并且在所有已启动子协程执行完毕之前不会结束。runBlocking 与 coroutineScope 的主要区别在于后者在等待所有子协程执行完毕时不会阻塞当前线程。
我们已经知道了 runBlocking 方法会创建一个新的协程,coroutineScope 函数看起来效果与 runBlocking 效果很像。但其实他们两者存在本质性的差异。
前面我们说了 runBlocking 是桥接阻塞代码与挂起代码之前的桥梁,其函数本身是阻塞的,但是可以在其内部运行 suspend 修饰的挂起函数。在内部所有子协程运行完毕之前,他是阻塞线程的。
而 coroutineScope 函数不同:该函数被 suspend 修饰,是一个挂起函数,前面我们说了挂起函数是不会阻塞线程的,它只会挂起协程,而不阻塞线程。