前言
Kotlin 协程(Coroutines)是 Android 和服务端开发者的必备技能。相比 Java 线程,协程更轻量、更易读、更安全。本文带你从零掌握 Kotlin 协程的核心用法。
一、协程 vs 线程
- 线程:操作系统调度,创建成本高(约1MB栈内存)
- 协程:用户态调度,创建成本极低(约几KB),可创建数十万个
- // Java 线程:10000个线程会OOM
- for (int i = 0; i < 10000; i++) {
- new Thread(() -> doWork()).start();
- }
- // Kotlin 协程:100000个协程轻松运行
- repeat(100_000) {
- GlobalScope.launch { doWork() }
- }
复制代码 二、第一个协程
- import kotlinx.coroutines.*
- fun main() = runBlocking {
- // 启动协程
- launch {
- delay(1000) // 非阻塞延迟
- println("World!")
- }
- println("Hello,")
- }
- // 输出:
- // Hello,
- // (1秒后) World!
复制代码 三、协程作用域(CoroutineScope)
- // 1. GlobalScope:全局作用域,生命周期跟随应用
- GlobalScope.launch {
- println("Global scope")
- }
- // 2. runBlocking:阻塞当前线程直到协程完成
- runBlocking {
- launch { println("runBlocking") }
- }
- // 3. coroutineScope:挂起当前协程,等待子协程完成
- suspend fun loadData() = coroutineScope {
- launch { fetchUser() }
- launch { fetchOrders() }
- }
- // 4. ViewModelScope(Android):跟随 ViewModel 生命周期
- viewModelScope.launch {
- val data = repository.fetchData()
- updateUI(data)
- }
复制代码 四、挂起函数(suspend)
- // 挂起函数:可在协程中暂停执行,不阻塞线程
- suspend fun fetchUser(): User {
- return withContext(Dispatchers.IO) {
- // 切换到 IO 线程执行网络请求
- api.getUser()
- }
- }
- // 调用挂起函数
- fun loadData() = viewModelScope.launch {
- showLoading()
- val user = fetchUser() // 挂起,等待结果
- updateUI(user) // 恢复执行
- hideLoading()
- }
复制代码 五、协程调度器(Dispatcher)
- // 1. Dispatchers.Main:主线程(UI 操作)
- withContext(Dispatchers.Main) {
- textView.text = "Updated"
- }
- // 2. Dispatchers.IO:IO 密集型(网络、数据库)
- withContext(Dispatchers.IO) {
- val data = api.fetchData()
- database.save(data)
- }
- // 3. Dispatchers.Default:CPU 密集型(排序、计算)
- withContext(Dispatchers.Default) {
- val sorted = list.sortedBy { it.id }
- }
- // 4. 自定义线程池
- val customDispatcher = Executors.newFixedThreadPool(4).asCoroutineDispatcher()
- withContext(customDispatcher) {
- heavyComputation()
- }
复制代码 六、异常处理
- // CoroutineExceptionHandler:全局异常捕获
- val handler = CoroutineExceptionHandler { _, e ->
- println("Caught: $e")
- }
- val job = GlobalScope.launch(handler) {
- throw RuntimeException("Error!")
- }
- // try-catch:局部异常处理
- try {
- val result = async {
- riskyOperation()
- }.await()
- } catch (e: Exception) {
- handleError(e)
- }
复制代码 七、实战:并发请求
- data class User(val id: Int, val name: String)
- data class Order(val id: Int, val userId: Int)
- suspend fun loadUserData(userId: Int): Pair<User, List<Order>> {
- return coroutineScope {
- // 并发执行两个请求
- val userDeferred = async { fetchUser(userId) }
- val ordersDeferred = async { fetchOrders(userId) }
-
- // 等待结果
- Pair(userDeferred.await(), ordersDeferred.await())
- }
- }
- // 对比 Java CompletableFuture
- // Kotlin 协程写法更简洁,无需回调链
复制代码 总结
Kotlin 协程让并发编程变得优雅。核心要点:
结构化并发
挂起函数
调度器
觉得有帮助请点赞收藏!有问题欢迎评论区交流
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |