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