Kotlin 协程 Coroutine

1、什么是协程?和线程有什么区别

答案

协程是轻量级线程 ,基于线程封装,由语言层调度,不是操作系统调度。

区别:

  1. 线程由 OS 调度、开销大;协程开销极小、可开上万个。
  2. 线程是抢占式 ;协程是协作式,主动挂起、恢复。
  3. 协程可非阻塞挂起,不阻塞当前线程。
  4. 协程自带上下文、作用域、生命周期,更适合 Android 异步开发。

2、协程的优点

答案

  1. 轻量、占用资源少,支持大量并发;
  2. 用同步写法写异步代码,告别嵌套回调;
  3. 自带作用域,可统一取消、防泄漏
  4. 灵活切换调度线程(主线程 / 子线程);
  5. 配合 Flow、Jetpack 生态适配更好。

3、什么是挂起函数 suspend?作用是什么

答案

suspend 修饰的函数是挂起函数

特点:

  1. 只能在协程或其他挂起函数中调用;
  2. 不会阻塞线程,只是挂起当前协程,让出线程执行其他任务;
  3. 耗时结束后自动恢复继续执行。

4、suspend 底层原理

答案

Kotlin 编译器把挂起函数编译成 状态机,把代码切分成多个状态片段;

挂起点保存上下文,恢复时从对应状态继续执行,实现无回调异步。

5、协程三大核心:协程作用域、调度器、生命周期

答案

  • 作用域 Scope:管理协程生命周期,统一取消、控制启停;
  • 调度器 Dispatcher:指定协程跑在哪个线程;
  • Job:协程任务句柄,可取消、监听完成状态。

6、四大调度器 Dispatcher 区别

答案

  • Dispatcher.Main:主线程,更新 UI;
  • Dispatcher.IO:子线程,适合网络、文件、数据库 IO;
  • Dispatcher.Default :子线程,适合CPU 密集型复杂计算;
  • Dispatcher.Unconfined:不指定线程,随上下文执行,几乎不用。

7、常用协程作用域有哪些

答案

  1. GlobalScope :全局作用域,生命周期跟 App 一致,不推荐,容易泄漏;
  2. viewModelScope :ViewModel 自带,ViewModel 销毁自动取消协程,防泄漏;
  3. lifecycleScope:Activity/Fragment 自带,页面销毁自动取消;
  4. 自定义 CoroutineScope 自己管理生命周期。

8、为什么不推荐用 GlobalScope

答案

GlobalScope 生命周期贯穿整个 App,页面退出无法自动取消;里面的网络、延时任务还在后台跑,极易造成内存泄漏、浪费资源

9、launch 和 async 区别

答案

  • launch :只执行任务,无返回值,返回 Job;
  • async :有返回值,返回 Deferred ,可用 await() 拿结果;适合需要获取异步返回值的场景。

10、await () 作用

答案

等待 async 协程执行完成,挂起当前协程,拿到返回结果;不会阻塞线程,只是协程挂起。

11、协程怎么取消?取消原理

答案

通过 Job.cancel () 取消协程;

协程在挂起点 会响应取消,抛出 CancellationException;作用域取消后,内部所有子协程全部级联取消

12、协程异常怎么处理?CoroutineExceptionHandler

答案

  1. 单个协程内部用 try-catch 包裹挂起函数;
  2. 全局统一异常用 CoroutineExceptionHandler
  3. launch 默认异常会崩溃;async 异常在 await 时才抛出。

13、协程结构化并发

结构化并发:子协程依附父协程作用域,父子生命周期绑定,自动取消、自动异常传递,杜绝协程泄漏。

核心三点

  1. 父子协程关系 协程有父子层级,子协程继承父Scope、Dispatcher、异常策略
  2. 结构化取消 父作用域一取消,所有子协程跟着全部级联取消,不用手动一个个解绑,天然防内存泄漏。
  3. 异常自动传播子协程抛异常,会向上传给父协程,统一捕获处理,不会静默崩溃、丢异常。

14、协程的启动模式几种

四种枚举

CoroutineStart 一共四种:DEFAULT、LAZY、ATOMIC、UNDISPATCHED

逐个极简解释

1、DEFAULT(默认)

立刻根据调度器调度执行,排队进入对应线程池,标准常规启动。

2、LAZY(懒启动)

不会自动执行 ,需要手动调用 start() / join() 才开始跑;适合需要延迟触发、手动控制时机的场景。

3、ATOMIC

立即在当前线程原子式启动 ,不可取消;在挂起之前,无法被取消,执行到第一个挂起点才响应取消。

4、UNDISPATCHED

直接在当前线程立刻执行 ,不切调度器;直到遇到第一个 suspend 挂起点,之后才按 Dispatcher 调度切换线程。

相关推荐
Jomurphys1 小时前
Compose 适配 - 通过 UiMediaScope 获取设备信息
android·compose
阿巴斯甜2 小时前
必看12
android
阿巴斯甜2 小时前
必看11
android
solo_992 小时前
Perftto 使用命令添加标签
android
阿巴斯甜2 小时前
必看10
android
阿巴斯甜2 小时前
必看9
android
阿巴斯甜2 小时前
必看6
android
angerdream3 小时前
Android手把手编写儿童手机远程监控App之SQLite详解
android
阿巴斯甜3 小时前
必看5
android