Kotlin 协程:串行/并行请求、async/await、coroutineScope 管理并发、重试机制

4 个核心知识点:串行/并行请求、async/awaitcoroutineScope 管理并发、重试机制。


前置准备

先添加协程依赖(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")
}

核心知识点

  1. async 必须在协程作用域中使用
  2. async 不阻塞线程,只挂起协程
  3. await() 会挂起当前协程,直到获取结果
  4. 多个 async自动并行执行

三、使用 coroutineScope 管理并发

coroutineScope结构化并发的核心,用于:

  1. 管理子协程的生命周期
  2. 所有子协程完成后才会退出
  3. 任一子协程失败,所有子协程都会被取消
  4. 父协程取消,子协程同步取消

实现:安全管理并发任务

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}")
    }
}

核心特性

  1. 支持自定义重试次数重试间隔
  2. 协程取消时不重试,避免资源浪费
  3. 统一异常处理,逻辑解耦
  4. 适用于网络请求、接口调用、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 次后,请求最终失败

总结

  1. 串行/并行:串行依赖结果、总耗时叠加;并行无依赖、效率更高
  2. async/await :创建并发任务,async 发起,await 取结果
  3. coroutineScope:结构化并发,统一管理生命周期、异常、取消
  4. 重试机制:高阶函数封装,支持次数/间隔配置,适配网络请求
相关推荐
山河梧念2 小时前
【保姆级教程】VMware虚拟机安装全流程
android·java·数据库
常利兵2 小时前
Kotlin类型魔法:Any、Unit、Nothing 深度探秘
android·开发语言·kotlin
y小花2 小时前
安卓vold服务
android·linux·运维
明天就是Friday2 小时前
Android实战项目⑤ Paging 3开发社交媒体信息流App 完整源码详解
android·媒体
宋拾壹3 小时前
php网站小程序接入抖音团购核销
android·小程序·php
莫逸风4 小时前
【java-core-collections】B+ 树深度解析
android·java·开发语言
我命由我123454 小时前
Android 开发问题:无法从存储库 “D:\keys\MyNotifications.jks“ 中读取密钥 MyNotifications.
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
AI玫瑰助手4 小时前
Python基础:字符串的切片操作(含正向反向索引)
android·开发语言·python
落羽的落羽4 小时前
【算法札记】练习 | Week2
android·linux·服务器·c++·python·算法·机器学习