kotlin-4

太棒了!现在让我们进入 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")
}

二十四、异步并发:同时执行多个任务

使用 asyncawait实现并发操作。

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 协程的核心概念!接下来可以探索:

  1. Flow 高级操作combinezipflatMapLatest等操作符
  2. 状态管理 :使用 StateFlowSharedFlow
  3. 测试协程 :使用 TestCoroutineDispatcherrunTest
  4. Android 上的协程:与 ViewModel、Lifecycle 集成
  5. 服务端协程:Ktor 框架的使用

协程是 Kotlin 生态中最强大的特性之一,它将彻底改变你处理异步编程的方式。尝试在实际项目中使用这些模式,你会发现代码变得更加简洁和易于维护!

相关推荐
whysqwhw2 小时前
kotlin-3
github
whysqwhw2 小时前
kotlin-1
github
whysqwhw2 小时前
kotlin-2
github
CoderJia程序员甲5 小时前
GitHub 热榜项目 - 日榜(2025-11-09)
github
labview_自动化5 小时前
GitHub笔记
笔记·github
知行力5 小时前
【GitHub每日速递 20251111】PyTorch:GPU加速、动态网络,深度学习平台的不二之选!
pytorch·深度学习·github
逛逛GitHub8 小时前
GitHub 开源 AI 好玩神器,自动记录你的一天。
前端·github
散峰而望8 小时前
C++入门(算法) - 习题
开发语言·c++·算法·github
mortimer9 小时前
faster-whisper本地转录简单方案
开源·github·openai