Kotlin 协程构建器 #
一、launch 构建器 #
1.1 基本用法 #
kotlin
fun main() = runBlocking {
val job = launch {
delay(1000)
println("Task completed")
}
println("Started")
job.join()
println("Finished")
}
1.2 返回 Job #
kotlin
fun main() = runBlocking {
val job: Job = launch {
repeat(5) { i ->
delay(500)
println("Working $i")
}
}
delay(1300)
job.cancel()
println("Cancelled")
}
1.3 启动模式 #
kotlin
fun main() = runBlocking {
// DEFAULT:立即启动
launch(start = CoroutineStart.DEFAULT) {
println("Default")
}
// LAZY:延迟启动
val lazyJob = launch(start = CoroutineStart.LAZY) {
println("Lazy")
}
lazyJob.start() // 手动启动
// ATOMIC:原子启动,不可取消
launch(start = CoroutineStart.ATOMIC) {
println("Atomic")
}
// UNDISPATCHED:立即执行直到第一个挂起点
launch(start = CoroutineStart.UNDISPATCHED) {
println("Undispatched")
}
}
二、async 构建器 #
2.1 基本用法 #
kotlin
fun main() = runBlocking {
val deferred: Deferred<String> = async {
delay(1000)
"Result"
}
println("Waiting...")
val result = deferred.await()
println("Result: $result")
}
2.2 并行执行 #
kotlin
suspend fun doSomething1(): Int {
delay(1000)
return 10
}
suspend fun doSomething2(): Int {
delay(1000)
return 20
}
fun main() = runBlocking {
val time = measureTimeMillis {
val a = async { doSomething1() }
val b = async { doSomething2() }
println("Sum: ${a.await() + b.await()}")
}
println("Time: $time ms") // 约 1000ms
}
2.3 懒加载 async #
kotlin
fun main() = runBlocking {
val deferred = async(start = CoroutineStart.LAZY) {
println("Computing...")
42
}
println("Before await")
val result = deferred.await() // 此时才开始执行
println("Result: $result")
}
2.4 async vs launch #
| 特性 | launch | async |
|---|---|---|
| 返回值 | Job | Deferred |
| 结果 | 无 | await() 获取 |
| 用途 | 执行任务 | 获取结果 |
三、runBlocking #
3.1 基本用法 #
kotlin
fun main() = runBlocking {
println("Start")
delay(1000)
println("End")
}
3.2 阻塞特性 #
kotlin
fun main() {
println("Before runBlocking")
runBlocking {
println("Inside runBlocking")
delay(1000)
}
println("After runBlocking")
}
3.3 使用场景 #
kotlin
// main 函数中使用
fun main() = runBlocking {
// 协程代码
}
// 测试中使用
@Test
fun testCoroutine() = runBlocking {
// 测试代码
}
// 桥接协程和阻塞代码
fun blockingFetch(): String = runBlocking {
fetchData()
}
3.4 注意事项 #
kotlin
// 不推荐:在协程中使用 runBlocking
fun main() = runBlocking {
launch {
// 不推荐:会阻塞协程
runBlocking {
delay(1000)
}
}
}
// 推荐:使用 coroutineScope
fun main() = runBlocking {
launch {
coroutineScope {
delay(1000)
}
}
}
四、coroutineScope #
4.1 基本用法 #
kotlin
suspend fun loadData() = coroutineScope {
launch {
delay(1000)
println("Task 1")
}
launch {
delay(500)
println("Task 2")
}
}
4.2 结构化并发 #
kotlin
suspend fun loadAllData() = coroutineScope {
val user = async { fetchUser() }
val posts = async { fetchPosts() }
AllData(user.await(), posts.await())
}
4.3 异常处理 #
kotlin
suspend fun process() = coroutineScope {
launch {
delay(100)
throw Exception("Error in child 1")
}
launch {
delay(200)
println("Child 2") // 不会执行
}
}
// 如果一个子协程失败,整个作用域取消
五、supervisorScope #
5.1 基本用法 #
kotlin
suspend fun process() = supervisorScope {
launch {
delay(100)
throw Exception("Error in child 1")
}
launch {
delay(200)
println("Child 2") // 会执行
}
}
// 子协程失败不影响其他子协程
5.2 与 coroutineScope 区别 #
kotlin
// coroutineScope:一个失败,全部取消
suspend fun withCoroutineScope() = coroutineScope {
launch { throw Exception() }
launch { println("This won't run") }
}
// supervisorScope:独立失败
suspend fun withSupervisorScope() = supervisorScope {
launch { throw Exception() }
launch { println("This will run") }
}
六、withContext #
6.1 切换上下文 #
kotlin
suspend fun loadData(): String {
return withContext(Dispatchers.IO) {
// 在 IO 线程执行
delay(1000)
"Data"
}
}
6.2 返回值 #
kotlin
suspend fun compute(): Int = withContext(Dispatchers.Default) {
// CPU 密集计算
42
}
6.3 withContext vs async #
kotlin
// withContext:顺序执行
suspend fun sequential() {
val a = withContext(Dispatchers.IO) { task1() }
val b = withContext(Dispatchers.IO) { task2() }
}
// async:并行执行
suspend fun parallel() = coroutineScope {
val a = async(Dispatchers.IO) { task1() }
val b = async(Dispatchers.IO) { task2() }
a.await() to b.await()
}
七、实战示例 #
7.1 并行数据加载 #
kotlin
suspend fun loadUserProfile(userId: Int): UserProfile {
return coroutineScope {
val user = async { fetchUser(userId) }
val posts = async { fetchPosts(userId) }
val followers = async { fetchFollowers(userId) }
UserProfile(
user = user.await(),
posts = posts.await(),
followers = followers.await()
)
}
}
7.2 超时控制 #
kotlin
suspend fun fetchWithTimeout(): String {
return withTimeout(1000) {
fetchData()
}
}
// 或返回 null
suspend fun fetchOrNull(): String? {
return withTimeoutOrNull(1000) {
fetchData()
}
}
7.3 重试机制 #
kotlin
suspend fun <T> retry(
times: Int,
block: suspend () -> T
): T {
repeat(times) { attempt ->
try {
return block()
} catch (e: Exception) {
if (attempt == times - 1) throw e
delay(1000)
}
}
throw Exception("Should not reach here")
}
八、最佳实践 #
8.1 选择合适的构建器 #
kotlin
// 需要结果:async
val result = async { compute() }.await()
// 不需要结果:launch
launch { logEvent() }
// 需要阻塞:runBlocking
fun main() = runBlocking { }
// 需要作用域:coroutineScope
suspend fun task() = coroutineScope { }
8.2 避免嵌套 runBlocking #
kotlin
// 不推荐
fun main() = runBlocking {
runBlocking { // 不必要
delay(1000)
}
}
// 推荐
fun main() = runBlocking {
coroutineScope {
delay(1000)
}
}
九、总结 #
协程构建器:
| 构建器 | 用途 | 返回值 |
|---|---|---|
| launch | 执行任务 | Job |
| async | 获取结果 | Deferred |
| runBlocking | 阻塞等待 | 结果 |
| coroutineScope | 结构化并发 | 结果 |
| supervisorScope | 独立失败 | 结果 |
下一步,让我们学习 协程上下文!
最后更新:2026-03-27