4. 协程超时
任务说明
本案例实现一个网络请求模拟器,使用withTimeout为耗时操作设置超时上限。当操作执行时间超过设定阈值时,协程会被取消并抛出TimeoutCancellationException,从而避免无限期等待。
核心实现
import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis
fun main() = runBlocking {
// 模拟耗时操作:延迟2秒后返回结果
suspend fun fetchUserData(): String {
delay(2000) // 模拟网络请求耗时
return "用户数据加载完成"
}
println("开始请求用户数据...")
val elapsed = measureTimeMillis {
try {
// 设置1秒超时,而请求需要2秒,必然触发超时
val result = withTimeout(1000) {
fetchUserData()
}
println("请求成功: $result")
} catch (e: TimeoutCancellationException) {
println("请求超时: ${e.message}")
println("异常类型: ${e::class.simpleName}")
}
}
println("总耗时: ${elapsed}ms")
// 演示超时后协程已被取消
println("协程是否活跃: ${coroutineContext.isActive}")
}
代码说明
withTimeout接收一个毫秒级超时参数和一个挂起函数块。当块内代码执行时间超过设定值时,协程会被自动取消,并抛出TimeoutCancellationException。该异常是CancellationException的子类,因此必须使用try-catch捕获,否则会导致协程静默取消。
运行方式
# 在项目build.gradle.kts中添加依赖
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
# 直接运行main函数
kotlin TimeoutExample.kt
验证方法
运行程序后,观察控制台输出。预期输出顺序为:
开始请求用户数据...
请求超时: Timed out waiting for 1000 ms
异常类型: TimeoutCancellationException
总耗时: 约1000ms
协程是否活跃: true
判定标准:程序在约1秒后终止,捕获到TimeoutCancellationException,且总耗时接近超时设定值而非请求的2秒,说明超时机制生效。
关键要点
withTimeout超时后会取消协程,但runBlocking外层协程不受影响,程序可继续执行后续代码- 必须显式捕获
TimeoutCancellationException,否则协程会静默取消且无法感知超时事件 - 超时时间从
withTimeout调用时刻开始计算,而非协程启动时刻