Kotlin 异步编程:完整实践指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Kotlin 异步编程:完整实践指南



现代应用程序需要高性能和快速响应。借助协程(coroutines)的 Kotlin 异步编程已成为处理网络请求、数据库和文件操作的事实标准。在本指南中,我们将解析核心概念,展示实战示例,并提供可直接用于项目的现成模板。



1. Kotlin 协程基础



协程是轻量级线程,允许在不阻塞主线程的情况下暂停函数执行。与传统线程不同,协程可以在任意时刻暂停并在之后恢复,使其成为异步操作的理想选择。



1.1. 添加依赖

首先,在 build.gradle.kts 中添加依赖:



dependencies {    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0") // 用于 Android}


1.2. 第一个协程

使用 runBlocking 创建一个简单的协程——它是同步世界与异步世界之间的桥梁:



import kotlinx.coroutines.*

fun main() = runBlocking { launch { delay(1000L) // 非阻塞延迟 println("世界!") } println("你好,") delay(2000L) // 等待协程完成}


在这个示例中,launch 启动了一个新协程,而 delay 是一个不会阻塞线程的挂起函数(suspend)。



2. Suspend 函数与结构化并发



2.1. 创建 suspend 函数

任何可以被暂停的函数都必须使用 suspend 修饰符标记。此类函数只能从协程或其他 suspend 函数中调用:



suspend fun fetchUserData(userId: String): User {    delay(2000L) // 模拟网络请求    return User(userId, "伊万·彼得罗夫")}

suspend fun fetchUserPosts(userId: String): List<Post> { delay(1500L) return listOf(Post("标题 1"), Post("标题 2"))}


2.2. 顺序执行

默认情况下,协程在同一个 launch 内按顺序执行:



fun main() = runBlocking {    val time = measureTimeMillis {        val user = fetchUserData("123")        val posts = fetchUserPosts("123")        println("${user.name} 有 ${posts.size} 篇帖子")    }    println("执行时间:$time 毫秒") // ~3500 毫秒}


2.3. 使用 async/await 并行执行

使用 async 和 await 实现并行执行:



fun main() = runBlocking {    val time = measureTimeMillis {        val user = async { fetchUserData("123") }        val posts = async { fetchUserPosts("123") }                println("${user.await().name} 有 ${posts.await().size} 篇帖子")    }    println("执行时间:$time 毫秒") // ~2000 毫秒(并行)}


3. 协程调度器与上下文



调度器决定了协程在哪个线程或线程池上执行。主要调度器包括:



  • Dispatchers.Default — 用于 CPU 密集型任务(默认)
  • Dispatchers.IO — 用于输入/输出操作(网络、文件)
  • Dispatchers.Main — 用于 UI 线程(Android、Swing)
  • Dispatchers.Unconfined — 不绑定到特定线程


3.1. Dispatchers.IO 示例

fun main() = runBlocking {    launch(Dispatchers.IO) {        // 网络请求        val response = httpClient.get("https://api.example.com/data")        withContext(Di                

博客

书籍推荐