1.4-协程基础与关键知识:并行协程的启动和交互

并行启动协程:async

在前面的章节已经讲解了启动协程的两种方式,一种是通过 launch 函数,一种是在协程内部通过挂起函数。

比如要启动两个并行执行的协程,可以开启两个协程:

scope.launch(Dispatchers.IO) {}
scope.launch(Dispatchers.IO) {}

如果想让两个不同线程的代码按顺序执行,那就启动一个协程然后在协程内部配合挂起函数串行切线程:

private fun coroutineStyle() = lifecycleScope.launch {
	val contributors = gitHub.contributors("square", "retrofit")
	showContributors(contributos)
}

如果我们希望让两个请求在它们都返回了之后,把它们的结果合并,然后再把合并的结果显示在界面里。我们尝试下用挂起函数看行不行:

private fun coroutineStyle() = lifecycleScope.launch {
	// 虽然最终是能拿到合并结果,但它们是串行执行的
	// 即返回了 contributors1 后再执行请求获取 contributors2 的请求
	val contributors1 = gitHub.contributors("square", "retrofit")
	val contributors2 = gitHub.contributors("square", "okhttp")
	showContributors(contributos1 + contributors2)
}

用上面的挂起函数虽然能满足我们拿到合并的结果,但是两个请求是串行执行的,这两个请求没有任何依赖关系,完全可以一起同时启动执行却要等待对方,这样就会导致网络耗时的翻倍

那有什么方式可以让两个网络请求同时执行,也能做到最终将结果合并呢?

协程除了提供 launch 启动协程外,其实还提供了 async 函数,通过它可以并行启动协程

private fun coroutineStyle() = lifecycleScope.launch {
	// 这里包一层 coroutineScope 只是为了结构化并发异常管理提供方便
	coroutineScope {
		val contributors1 = async { gitHub.contributors("square", "retrofit") }
		val contributors2 = async { gitHub.contributors("square", "okhttp") }
		showContributors(contributos1.await() + contributors2.await())
	}
}

使用 async 函数可以启动协程并行执行,最后通过 await 函数等待结果

我们可以看下 async 函数是有返回值返回的,类型为 Deferred:

Builders.common.kt

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
}

协程之间互相等待:join

除了 async 之外,如果你只是希望两个并行流程在顺序上有某种依赖而不依赖结果,可以用 join 函数,可以做到协程之间互相等待

scope.launch {
	val initJob = launch { init () }
	val contributors = gitHub.contributors("square", "retrofit")
	// processData 依赖 init 的执行结束,用 join 等待执行结束后再继续
	initJob.join()
	processData()
}

总结

  • 启动协程有两个函数:launch 和 async,async 可以并行启动协程,最后通过 await 等待结果返回,常用于多个处理同时执行后合并结果的操作

  • 如果你只是希望两个并行流程在顺序上有某种依赖而不依赖结果,可以用 join 函数,可以做到协程之间互相等待

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值