4 个核心知识点:串行/并行请求、async/await、coroutineScope 管理并发、重试机制。
前置准备
先添加协程依赖(Gradle),确保环境可用:
gradle
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3'
}
统一模拟网络请求工具函数(延时模拟请求耗时):
kotlin
import kotlinx.coroutines.*
import kotlin.coroutines.cancellation.CancellationException
// 模拟网络请求1:获取用户信息
suspend fun fetchUserInfo(): String {
delay(1000) // 模拟1秒请求耗时
return "用户信息:张三"
}
// 模拟网络请求2:获取订单信息
suspend fun fetchOrderInfo(): String {
delay(1000) // 模拟1秒请求耗时
return "订单信息:订单#123"
}
// 模拟会失败的请求(用于重试机制)
suspend fun fetchFailedData(): String {
delay(500)
throw RuntimeException("请求失败!")
}
一、串行请求 vs 并行请求
1. 串行请求
定义 :一个请求执行完成后,再执行下一个,总耗时 = 所有请求耗时之和。
适用场景:第二个请求依赖第一个请求的结果。
kotlin
// 串行请求
suspend fun serialRequest() {
val start = System.currentTimeMillis()
// 先执行第一个请求
val user = fetchUserInfo()
// 再执行第二个请求
val order = fetchOrderInfo()
val end = System.currentTimeMillis()
println("【串行】结果:$user, $order")
println("【串行】总耗时:${end - start} ms") // 约 2000ms
}
2. 并行请求
定义 :多个请求同时执行,总耗时 = 耗时最长的单个请求。
适用场景:多个请求无依赖关系,追求效率。
kotlin
// 并行请求(async+await 基础版)
suspend fun parallelRequest() = coroutineScope {
val start = System.currentTimeMillis()
// 异步发起请求1(不阻塞,直接执行)
val userDeferred = async { fetchUserInfo() }
// 异步发起请求2(和请求1同时执行)
val orderDeferred = async { fetchOrderInfo() }
// 等待两个请求结果
val user = userDeferred.await()
val order = orderDeferred.await()
val end = System.currentTimeMillis()
println("【并行】结果:$user, $order")
println("【并行】总耗时:${end - start} ms") // 约 1000ms
}
核心区别
- 串行:阻塞执行,总耗时叠加
- 并行:同时执行,总耗时取最大值
二、使用 async/await 实现并发
async 是协程创建并发任务 的核心函数,返回 Deferred(延迟结果),await() 用于获取结果。
完整实现
kotlin
suspend fun asyncAwaitDemo() {
// coroutineScope:提供协程作用域
val result = coroutineScope {
// async 1:并发任务1
val user = async {
println("获取用户信息...")
fetchUserInfo()
}
// async 2:并发任务2
val order = async {
println("获取订单信息...")
fetchOrderInfo()
}
// await:等待任务完成,获取结果
// 两个任务同时执行,无需互相等待
"用户:${user.await()},订单:${order.await()}"
}
println("【async/await】最终结果:$result")
}
核心知识点
async必须在协程作用域中使用async不阻塞线程,只挂起协程await()会挂起当前协程,直到获取结果- 多个
async会自动并行执行
三、使用 coroutineScope 管理并发
coroutineScope 是结构化并发的核心,用于:
- 管理子协程的生命周期
- 所有子协程完成后才会退出
- 任一子协程失败,所有子协程都会被取消
- 父协程取消,子协程同步取消
实现:安全管理并发任务
kotlin
suspend fun coroutineScopeDemo() {
try {
// 结构化并发:作用域内所有协程统一管理
val (user, order) = coroutineScope {
// 并发任务1
val userTask = async { fetchUserInfo() }
// 并发任务2
val orderTask = async { fetchOrderInfo() }
// 直接返回两个结果
userTask.await() to orderTask.await()
}
println("【coroutineScope】结果:$user, $order")
} catch (e: Exception) {
println("【作用域管理】请求失败:${e.message}")
}
}
核心优势(结构化并发)
- 自动取消:作用域销毁/失败,所有子协程自动取消
- 无泄漏:不会出现失控的后台协程
- 异常安全:异常统一捕获,不会丢失
四、重试机制实现
网络请求必备:请求失败后,自动重试 N 次,支持延迟重试。
通用重试高阶函数
kotlin
/**
* 重试机制
* @param times 最大重试次数
* @param delay 重试间隔时间(毫秒)
* @param block 执行的挂起函数
*/
suspend fun <T> retry(
times: Int = 3,
delay: Long = 1000,
block: suspend () -> T
): T {
repeat(times) {
try {
// 执行请求
return block()
} catch (e: CancellationException) {
// 协程取消,直接抛出,不重试
throw e
} catch (e: Exception) {
// 其他异常:打印日志,延迟后重试
println("【重试】第 ${it + 1} 次失败,${delay}ms 后重试...")
delay(delay)
}
}
// 所有重试都失败,抛出最终异常
throw RuntimeException("重试 $times 次后,请求最终失败")
}
使用重试机制
kotlin
suspend fun retryDemo() {
try {
// 重试3次,每次间隔1秒
val data = retry(times = 3, delay = 1000) {
fetchFailedData() // 模拟失败的请求
}
println(data)
} catch (e: Exception) {
println("【重试机制】最终结果:${e.message}")
}
}
核心特性
- 支持自定义重试次数 和重试间隔
- 协程取消时不重试,避免资源浪费
- 统一异常处理,逻辑解耦
- 适用于网络请求、接口调用、IO 操作
最终测试代码(一键运行)
kotlin
fun main() = runBlocking {
println("===== 1. 串行 vs 并行 =====")
serialRequest()
parallelRequest()
println("\n===== 2. async/await 并发 =====")
asyncAwaitDemo()
println("\n===== 3. coroutineScope 管理并发 =====")
coroutineScopeDemo()
println("\n===== 4. 重试机制 =====")
retryDemo()
}
运行结果
===== 1. 串行 vs 并行 =====
【串行】结果:用户信息:张三, 订单信息:订单#123
【串行】总耗时:2010 ms
【并行】结果:用户信息:张三, 订单信息:订单#123
【并行】总耗时:1006 ms
===== 2. async/await 并发 =====
获取用户信息...
获取订单信息...
【async/await】最终结果:用户:用户信息:张三,订单:订单信息:订单#123
===== 3. coroutineScope 管理并发 =====
【coroutineScope】结果:用户信息:张三, 订单信息:订单#123
===== 4. 重试机制 =====
【重试】第 1 次失败,1000ms 后重试...
【重试】第 2 次失败,1000ms 后重试...
【重试】第 3 次失败,1000ms 后重试...
【重试机制】最终结果:重试 3 次后,请求最终失败
总结
- 串行/并行:串行依赖结果、总耗时叠加;并行无依赖、效率更高
- async/await :创建并发任务,
async发起,await取结果 - coroutineScope:结构化并发,统一管理生命周期、异常、取消
- 重试机制:高阶函数封装,支持次数/间隔配置,适配网络请求