/** * 第 9 章 · 协程基础 — 综合示例 * * 涵盖:runBlocking / launch / async / await / * suspend / delay / coroutineScope / supervisorScope / * withContext / Dispatchers / Flow / withTimeout * * 依赖:implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") */ import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import kotlin.system.measureTimeMillis suspend fun fetchUser(id: String): String { delay(500) return "User[$id]" } suspend fun fetchOrders(userId: String): List { delay(700) return listOf("Order-1", "Order-2", "Order-3") } suspend fun fetchPayment(orderId: String): String { delay(300) return "Payment[$orderId]=¥100" } fun main() = runBlocking { println("=== 1. 串行 vs 并发 ===") val seqTime = measureTimeMillis { val u = fetchUser("u1") val o = fetchOrders("u1") val p = fetchPayment(o[0]) println(" 串行结果: $u, ${o.size} orders, $p") } println(" 串行耗时: ${seqTime}ms\n") val parTime = measureTimeMillis { // 这里只能用 async 因为后面要用结果。但 user 和 orders 实际不依赖(演示并发) val uDeferred = async { fetchUser("u1") } val oDeferred = async { fetchOrders("u1") } val u = uDeferred.await() val o = oDeferred.await() val p = fetchPayment(o[0]) println(" 并发结果: $u, ${o.size} orders, $p") } println(" 并发耗时: ${parTime}ms (节省了 ~500ms)") println("\n=== 2. launch:fire and forget ===") val job = launch { delay(300) println(" [子协程] 跑完了") } println(" [main] 主协程继续往下跑") job.join() // 等子协程结束 println(" [main] 子协程结束后我才退出") println("\n=== 3. async + await:要返回值 ===") val total = withContext(Dispatchers.Default) { val a = async { delay(200); 10 } val b = async { delay(200); 20 } a.await() + b.await() } println(" total = $total (并发执行只用了 ~200ms)") println("\n=== 4. 异常处理 ===") try { coroutineScope { launch { throw RuntimeException("子协程 A 挂了") } launch { delay(500) println(" 子协程 B 跑完") // 不会执行!coroutineScope 会取消所有兄弟 } } } catch (e: Exception) { println(" ✅ 捕获到: ${e.message}") } println("\n=== 5. supervisorScope:子协程互相隔离 ===") supervisorScope { launch { try { throw RuntimeException("子协程 A 挂了") } catch (e: Exception) { println(" A 自己处理了异常: ${e.message}") } } launch { delay(200) println(" ✅ 子协程 B 不受 A 影响,正常跑完") } } println("\n=== 6. withTimeout:超时控制 ===") try { withTimeout(800) { delay(2000) // 超时! println(" 这条不会打印") } } catch (e: TimeoutCancellationException) { println(" ⏰ 超时触发: ${e.message}") } println("\n=== 7. 取消协程 ===") val cancelJob = launch { try { repeat(10) { i -> delay(200) println(" 在跑第 $i 次") } } catch (e: CancellationException) { println(" ✋ 协程被取消了") } } delay(500) cancelJob.cancelAndJoin() println(" cancel 完成") println("\n=== 8. Flow:异步数据流 ===") fun numbers(): Flow = flow { for (i in 1..5) { delay(200) emit(i) println(" [flow] 发出了 $i") } } println(" 开始 collect:") numbers() .filter { it % 2 == 0 } .map { it * it } .collect { println(" 收到: $it") } println("\n=== 9. Flow 的"冷"特性 ===") val coldFlow = flow { println(" [flow 块] 开始执行") emit(1); emit(2) } println(" 第一次 collect:") coldFlow.collect { println(" 收到 $it") } println(" 第二次 collect:") coldFlow.collect { println(" 收到 $it") } println(" → flow 块被执行了 2 次(每次 collect 都重跑)") println("\n=== 10. 实战:并发批量请求 ===") val ids = listOf("p1", "p2", "p3", "p4", "p5") val products = ids.map { id -> async { fetchUser(id) } }.awaitAll() println(" 并发拿到 ${products.size} 个: $products") println("\n=== 11. Dispatchers 切换 ===") println(" 当前线程: ${Thread.currentThread().name}") withContext(Dispatchers.IO) { println(" IO 线程: ${Thread.currentThread().name}") } withContext(Dispatchers.Default) { println(" Default 线程: ${Thread.currentThread().name}") } println(" 回到原线程: ${Thread.currentThread().name}") }