Android开发:Kotlin协程并发模型(人话版)

张开发
2026/4/15 20:29:57 15 分钟阅读

分享文章

Android开发:Kotlin协程并发模型(人话版)
一、核心基础协程的并发与并行1. 核心前提并发 ≠ 并行并发单核CPU场景下任务快速切换毫秒/微秒级看起来像同时执行本质是「轮流执行」如单线程内的协程、单线程多任务。并行多核CPU场景下多个任务在不同核心上物理同时执行本质是「真正同时跑」。2. 协程的并发与并行逻辑单线程内的协程仅能实现「并发」依赖协程主动让出CPU如await、IO等待切换速度比线程快100~1000倍无内核切换开销。协程的「并行」无法单独实现必须依托「多线程/多进程 多核CPU」—— 协程挂靠在操作系统线程上多个线程分配到不同CPU核心实现协程并行。关键结论同一时刻真正在CPU上运行的协程数量 ≤ 活跃的操作系统线程数量协程必须挂靠线程执行一个线程同一时刻只能执行一个协程。二、协程运行机制结合实战代码1. 实战代码解析IO并行请求suspendfunloadData():CombinedDatacoroutineScope{valuserDeferredasync(Dispatchers.IO){api.getUser()}valnewsDeferredasync(Dispatchers.IO){api.getNews()}CombinedData(userDeferred.await(),newsDeferred.await())}2. 逐步运行逻辑进入coroutineScope创建父协程父协程运行在调用它的线程如安卓主线程。启动async协程两个async分别创建子协程指定Dispatchers.IO提交到IO线程池线程池分配空闲线程如Thread-IO1、Thread-IO2执行网络请求async不等待直接返回Deferred对象代码继续执行。执行await()父协程调用await()的瞬间会「挂起」并「立刻释放当前占用的线程」无需等待所有await或所有子协程完成。协程恢复子协程执行完成网络请求结束父协程重新获取线程继续执行后续代码组装并返回CombinedData。3. 关键细节await()与线程释放任意一个协程父协程/子协程调用await()或任何挂起函数调用者协程会立即挂起同时释放当前占用的线程。线程释放与协程作用域coroutineScope无关coroutineScope仅负责等待所有子协程完成不管理线程释放线程释放由「协程挂起」决定。恢复后线程的归属若协程绑定Dispatchers.Main主线程恢复后必回主线程若绑定Dispatchers.IO/Default线程池恢复后线程可能变化随机分配线程池中的空闲线程。三、协程调度器详解Dispatchers1. 两大核心调度器Kotlin官方规则调度器适用场景最大线程数规则核心特点Dispatchers.DefaultCPU密集型任务等于CPU核心数如8核8个10核10个线程全程占用CPU多开线程会增加切换开销降低效率Dispatchers.IOIO密集型任务max(64, CPU核心数)绝大多数设备64线程99%时间在等待如网络、文件读写不占CPU多开线程提升并发效率2. 关键补充CPU密集型任务全程纯计算、不等待如图片压缩、JSON解析、加密解密、复杂算法运算必须用Default。IO密集型任务主要时间在等待如网络请求、文件读写、数据库操作必须用IO。IO线程上限64的原因64个线程足够支撑移动端极高并发再多会浪费内存线程栈占用和增加内核切换开销是行业通用最优值。四、常见疑问答疑高频踩坑点1. 疑问启动100个asyncIO调度器线程池不够用会怎样解答不会崩溃、不卡顿、不报错。IO线程池默认上限64剩余36个协程会进入轻量级等待队列等有空闲线程IO线程完成等待、释放线程后自动取出执行排队的协程无内存开销不占用CPU。2. 疑问8核手机IO线程上限6410核是不是80解答不是。IO线程上限遵循max(64, CPU核心数)只要CPU核心数≤64无论8核、10核、32核上限都是64只有CPU核心数64如服务器65核上限才等于核心数。3. 疑问父协程中多个await需要所有await都调用才释放线程吗解答不需要。只要执行任意一个await()调用它的协程就会立即挂起、释放线程后续await()会再次挂起、释放线程直到所有子协程完成协程恢复。4. 疑问协程挂起await后恢复时一定能回到原来的线程吗解答不一定看调度器绑定Dispatchers.Main主线程恢复后必回主线程绑定Dispatchers.IO/Default线程池恢复后可能切换到线程池中的其他空闲线程。五、核心总结必记协程用户态轻量级任务依赖线程执行无线程无法运行核心优势是「用户态快速切换」和「挂起不阻塞线程」。并行协程需依托多线程多核CPU同一时刻运行的协程数≤线程数并发单线程内协程快速切换无需多核。调度器选择CPU密集用Default线程数核心数IO密集用IO上限64主线程操作绑定Main。await()调用即挂起、释放线程恢复线程由调度器决定coroutineScope仅负责等待子协程不管理线程。

更多文章