目录
启动协程的基本方式
1.GlobalScope.launch
代码示例:
fun testGlobalScope() { GlobalScope.launch { println("Coroutinue started!") delay(1000L) println("Hello World!") } println("After launch!") Thread.sleep(2000L) println("Process end!") } /** * After launch! * Coroutinue started! * Hello World! * Process end! */
@DelicateCoroutinesApi public object GlobalScope : CoroutineScope { /** * Returns [EmptyCoroutineContext]. */ override val coroutineContext: CoroutineContext get() = EmptyCoroutineContext }
public fun CoroutineScope.launch( context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit ): Job { val newContext = newCoroutineContext(context) val coroutine = if (start.isLazy) LazyStandaloneCoroutine(newContext, block) else StandaloneCoroutine(newContext, active = true) coroutine.start(start, coroutine, block) return coroutine }
launch函数是CoroutineScope的扩展函数,它有三个参数:
- context: CoroutineContext = EmptyCoroutineContext, 第一个参数是协程上下文,它的默认值是 EmptyCoroutineContext,如果不传这个参数,默认就会使用 EmptyCoroutineContext。也可以传入 Kotlin 官方为我们提供的 Dispatchers,来指定协程运行的线程池。(Dispatchers.IO、Dispatchers.Unconfined、Dispatchers.Main)
- start: CoroutineStart = CoroutineStart.DEFAULT,第二个参数是协程的启动模式,默认值是CoroutineStart.DEFAULT,CoroutineStart 是一个枚举类,一共有:DEFAULT、LAZY、ATOMIC、UNDISPATCHED。
- block: suspend CoroutineScope.() -> Unit,第三个参数是函数类型block,它的类型是suspend CoroutineScope.() -> Unit。本质是一个挂起函数。
- 函数的返回值是一个 Job,它其实代表的是协程的句柄,并不能返回协程的执行结果。
2.runBlocking 启动协程
代码示例
fun testRunBlocking2() { runBlocking { println("Coroutinue started!") delay(1000L) println("Hello World!") } println("After Launch") Thread.sleep(2000L) println("Process end") } /** * Coroutinue started! * Hello World! * After Launch * Process end */
@Throws(InterruptedException::class) public actual fun <T> runBlocking(context: CoroutineContext, block: suspend CoroutineScope.() -> T): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } val currentThread = Thread.currentThread() val contextInterceptor = context[ContinuationInterceptor] val eventLoop: EventLoop? val newContext: CoroutineContext if (contextInterceptor == null) { // create or use private event loop if no dispatcher is specified eventLoop = ThreadLocalEventLoop.eventLoop newContext = GlobalScope.newCoroutineContext(context + eventLoop) } else { // See if context's interceptor is an event loop that we shall use (to support TestContext) // or take an existing thread-local event loop if present to avoid blocking it (but don't create one) eventLoop = (contextInterceptor as? EventLoop)?.takeIf { it.shouldBeProcessedFromContext() } ?: ThreadLocalEventLoop.currentOrNull() newContext = GlobalScope.newCoroutineContext(context) } val coroutine = BlockingCoroutine<T>(newContext, currentThread, eventLoop) coroutine.start(CoroutineStart.DEFAULT, coroutine, block) return coroutine.joinBlocking() }
runBlocking是普通函数,第一个参数:context: CoroutineContext,协程上下文。第二个参数是函数类型,block: suspend CoroutineScope.() -> T,函数类型是有返回值类型 T 的,与 runBlocking 的返回值类型是一样的,runBlocking 其实是可以从协程当中返回执行结果的。
fun testRunBlocking() { val runBlockingResult = runBlocking { delay(500L) return@runBlocking "HaHa" } println("result:$runBlockingResult") } result:HaHa
runBlocking特点:
runBlocking 启动的协程会阻塞当前线程的执行。
3.async启动协程
使用 async{} 创建协程,可以通过它返回的Deferred拿到协程的执行结果。
代码示例
fun testAsync() { runBlocking { val deferred = async { println("do async:${Thread.currentThread().name}") delay(1000L) return@async "do completed" } println("After async:${Thread.currentThread().name}") val result = deferred.await() println("Result is: $result") } } After async:main @coroutine#1 do async:main @coroutine#2 Result is: do completed
public fun <T> CoroutineScope.async( context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> T ): Deferred<T> { val newContext = newCoroutineContext(context) val coroutine = if (start.isLazy) LazyDeferredCoroutine(newContext, block) else DeferredCoroutine<T>(newContext, active = true) coroutine.start(start, coroutine, block) return coroutine }
async注意点
- async 启动协程以后,不会阻塞当前程序的执行流程。
- async{}的返回值,是一个 Deferred 对象,它的 await() 方法,就可以拿到协程的执行结果。
- await只是等待执行完,并不是触发执行。