太棒了!现在让我们进入 Kotlin 最激动人心的部分------协程 和现代异步编程。这将彻底改变你处理并发和异步任务的方式。
Kotlin 协程:重新定义异步编程
二十二、协程基础:轻量级线程
协程是 Kotlin 用于异步编程的解决方案,比线程更轻量、更高效。
kotlin
import kotlinx.coroutines.*
fun main() {
println("主线程开始: ${Thread.currentThread().name}")
// 启动一个协程
GlobalScope.launch {
println("协程开始: ${Thread.currentThread().name}")
delay(1000L) // 非阻塞延迟
println("协程结束: ${Thread.currentThread().name}")
}
println("主线程继续执行: ${Thread.currentThread().name}")
Thread.sleep(2000L) // 阻塞主线程,等待协程完成
println("主线程结束")
}
// 输出:
// 主线程开始: main
// 主线程继续执行: main
// 协程开始: DefaultDispatcher-worker-1
// 协程结束: DefaultDispatcher-worker-1
// 主线程结束
关键概念:
launch: 启动一个不返回结果的协程delay(): 非阻塞的挂起函数- 协程运行在后台线程池,不会阻塞主线程
二十三、挂起函数:异步操作的基石
挂起函数是协程的核心,用 suspend关键字标记。
kotlin
import kotlinx.coroutines.*
suspend fun fetchUserData(userId: Int): String {
delay(1000L) // 模拟网络请求
return "用户 $userId 的数据"
}
suspend fun fetchUserPosts(userId: Int): String {
delay(1500L) // 模拟数据库查询
return "用户 $userId 的帖子"
}
fun main() = runBlocking {
val time = measureTimeMillis {
val userData = fetchUserData(1)
val userPosts = fetchUserPosts(1)
println("$userData, $userPosts")
}
println("顺序执行耗时: ${time}ms")
}
二十四、异步并发:同时执行多个任务
使用 async和 await实现并发操作。
kotlin
import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis
fun main() = runBlocking {
val time = measureTimeMillis {
// 同时启动两个异步任务
val userDataDeferred = async { fetchUserData(1) }
val userPostsDeferred = async { fetchUserPosts(1) }
// 等待两个任务都完成
val userData = userDataDeferred.await()
val userPosts = userPostsDeferred.await()
println("$userData, $userPosts")
}
println("并发执行耗时: ${time}ms") // 时间接近最长任务的时间
}
// 输出:
// 用户 1 的数据, 用户 1 的帖子
// 并发执行耗时: 1506ms (而不是 1000 + 1500 = 2500ms)
二十五、协程上下文与调度器
控制协程在哪个线程上运行。
scss
import kotlinx.coroutines.*
fun main() = runBlocking {
// 在不同调度器上启动协程
launch { // 继承父协程的上下文
println("默认调度器: ${Thread.currentThread().name}")
}
launch(Dispatchers.Unconfined) { // 不受限制,在第一个挂起点之前运行在调用者线程
println("不受限制: ${Thread.currentThread().name}")
}
launch(Dispatchers.Default) { // CPU 密集型任务
println("默认调度器: ${Thread.currentThread().name}")
}
launch(Dispatchers.IO) { // I/O 密集型任务
println("IO 调度器: ${Thread.currentThread().name}")
}
launch(newSingleThreadContext("MyThread")) { // 专用线程
println("专用线程: ${Thread.currentThread().name}")
}
}
二十六、结构化并发:避免资源泄漏
使用 coroutineScope实现结构化并发。
kotlin
import kotlinx.coroutines.*
fun main() = runBlocking {
// 结构化并发:所有子协程完成后,父协程才完成
val result = coroutineScope {
val userData = async { fetchUserData(1) }
val userPosts = async { fetchUserPosts(1) }
"结果: ${userData.await()} + ${userPosts.await()}"
}
println(result)
}
// 处理异常的结构化并发
suspend fun fetchDataSafely(): Result<String> = coroutineScope {
try {
val data = async {
delay(500L)
if (System.currentTimeMillis() % 2 == 0L) {
throw RuntimeException("模拟错误")
}
"获取的数据"
}.await()
Result.success(data)
} catch (e: Exception) {
Result.failure(e)
}
}
二十七、流(Flow):异步数据流
Flow 是 Kotlin 的响应式流处理,类似 RxJava。
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
// 创建流
fun simpleFlow(): Flow<Int> = flow {
println("流开始")
for (i in 1..3) {
delay(100L) // 模拟异步工作
emit(i) // 发射值
}
}
// 流的中间操作
fun processNumbers(): Flow<String> = flow {
for (i in 1..5) {
emit(i)
}
}.filter { it % 2 == 0 } // 过滤偶数
.map { "数字: $it" } // 转换
.onEach { println("处理: $it") } // 副作用
fun main() = runBlocking {
// 收集流
simpleFlow().collect { value ->
println("收集到: $value")
}
println("--- 带中间操作的流 ---")
processNumbers().collect { println("最终结果: $it") }
}
二十八、通道(Channel):协程间通信
Channel 用于协程之间的通信。
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
val channel = Channel<String>()
// 生产者协程
launch {
val users = listOf("Alice", "Bob", "Charlie")
for (user in users) {
channel.send(user) // 发送数据
delay(100L)
}
channel.close() // 关闭通道
}
// 消费者协程
launch {
for (user in channel) { // 接收数据
println("收到用户: $user")
}
println("通道已关闭")
}
}
二十九、实战:构建完整的异步应用
让我们构建一个完整的用户信息获取系统。
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.system.measureTimeMillis
// 数据类
data class User(val id: Int, val name: String, val email: String)
data class Post(val id: Int, val userId: Int, val title: String, val content: String)
data class UserProfile(val user: User, val posts: List<Post>, val friends: List<User>)
// 模拟远程数据源
object UserRepository {
suspend fun getUser(id: Int): User {
delay(500L) // 模拟网络延迟
return User(id, "用户$id", "user$id@example.com")
}
suspend fun getUserPosts(userId: Int): List<Post> {
delay(300L)
return listOf(
Post(1, userId, "标题1", "内容1"),
Post(2, userId, "标题2", "内容2")
)
}
suspend fun getUserFriends(userId: Int): List<User> {
delay(400L)
return listOf(
User(userId + 1, "朋友1", "friend1@example.com"),
User(userId + 2, "朋友2", "friend2@example.com")
)
}
}
// 业务逻辑层
class UserService {
suspend fun getUserProfile(userId: Int): UserProfile = coroutineScope {
val userDeferred = async { UserRepository.getUser(userId) }
val postsDeferred = async { UserRepository.getUserPosts(userId) }
val friendsDeferred = async { UserRepository.getUserFriends(userId) }
UserProfile(
user = userDeferred.await(),
posts = postsDeferred.await(),
friends = friendsDeferred.await()
)
}
// 使用 Flow 实现实时更新
fun getUserProfileStream(userId: Int): Flow<UserProfile> = flow {
while (true) {
val profile = getUserProfile(userId)
emit(profile)
delay(5000L) // 每5秒更新一次
}
}
}
// UI 层(模拟)
fun main() = runBlocking {
val userService = UserService()
println("=== 获取用户资料 ===")
val time = measureTimeMillis {
val profile = userService.getUserProfile(1)
println("用户: ${profile.user.name}")
println("帖子数量: ${profile.posts.size}")
println("好友数量: ${profile.friends.size}")
}
println("耗时: ${time}ms")
println("\n=== 实时数据流 ===")
// 模拟实时数据流(只收集3次)
userService.getUserProfileStream(1)
.take(3) // 只取3个值
.collect { profile ->
println("实时更新: ${profile.user.name} - 帖子: ${profile.posts.size}")
}
}
三十、异常处理与超时控制
scss
import kotlinx.coroutines.*
fun main() = runBlocking {
// 1. 基本的异常处理
val job = launch {
try {
delay(1000L)
throw RuntimeException("测试异常")
} catch (e: Exception) {
println("捕获异常: ${e.message}")
}
}
job.join()
// 2. 协程异常处理器
val handler = CoroutineExceptionHandler { _, exception ->
println("协程异常处理器捕获: ${exception.message}")
}
val job2 = launch(handler) {
throw RuntimeException("被处理器捕获的异常")
}
job2.join()
// 3. 超时控制
try {
withTimeout(1300L) {
repeat(1000) { i ->
println("任务 $i")
delay(500L)
}
}
} catch (e: TimeoutCancellationException) {
println("任务超时")
}
// 4. 超时返回默认值
val result = withTimeoutOrNull(1300L) {
delay(1000L)
"成功结果"
} ?: "超时默认值"
println("结果: $result")
}
三十一、高级模式:生产者-消费者模式
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun CoroutineScope.produceUsers() = produce {
var id = 1
while (true) {
send(User(id, "用户$id", "user$id@example.com"))
delay(200L)
id++
if (id > 5) break // 只生产5个用户
}
}
fun CoroutineScope.processUser(userChannel: ReceiveChannel<User>) = produce {
for (user in userChannel) {
delay(100L) // 模拟处理时间
send("已处理: ${user.name}")
}
}
fun main() = runBlocking {
val userProducer = produceUsers()
val processor = processUser(userProducer)
// 消费处理结果
for (result in processor) {
println(result)
}
println("处理完成")
}
下一步学习方向
你现在已经掌握了 Kotlin 协程的核心概念!接下来可以探索:
- Flow 高级操作 :
combine、zip、flatMapLatest等操作符 - 状态管理 :使用
StateFlow和SharedFlow - 测试协程 :使用
TestCoroutineDispatcher和runTest - Android 上的协程:与 ViewModel、Lifecycle 集成
- 服务端协程:Ktor 框架的使用
协程是 Kotlin 生态中最强大的特性之一,它将彻底改变你处理异步编程的方式。尝试在实际项目中使用这些模式,你会发现代码变得更加简洁和易于维护!