MST

星途 面试题库

面试题:Kotlin协程中如何处理异常

在Kotlin协程中,有多种方式处理异常,请详细描述try - catch块、CoroutineExceptionHandler以及supervisorScope在处理协程异常方面的原理、使用场景及区别。
49.0万 热度难度
编程语言Kotlin

知识考点

AI 面试

面试题答案

一键面试

try - catch块

  • 原理:在协程代码块内使用try - catch,其原理与普通Java或Kotlin代码中的try - catch类似,通过在try块中包裹可能抛出异常的代码,catch块捕获并处理异常。协程的挂起函数同样可以被包裹在try - catch块中,当挂起函数抛出异常时,catch块能够捕获。
  • 使用场景:适用于在单个协程内部对特定的、已知类型的异常进行捕获和处理。例如,在执行网络请求的协程中,处理可能的IOException等网络相关异常。
  • 示例
import kotlinx.coroutines.*

fun main() = runBlocking {
    try {
        launch {
            throw IOException("Network error")
        }.join()
    } catch (e: IOException) {
        println("Caught IOException: $e")
    }
}

CoroutineExceptionHandler

  • 原理CoroutineExceptionHandler是一个用于处理未捕获异常的处理器。当协程因未被try - catch捕获的异常而终止时,会调用CoroutineExceptionHandlerhandleException方法。它可以被添加到CoroutineScope中,用于处理该作用域内所有未捕获异常。
  • 使用场景:适用于在多个协程间统一处理未捕获异常,例如在整个应用的全局协程作用域中,对所有未处理异常进行日志记录、崩溃上报等通用处理。
  • 示例
import kotlinx.coroutines.*

val handler = CoroutineExceptionHandler { _, exception ->
    println("Caught $exception")
}

fun main() = runBlocking {
    GlobalScope.launch(handler) {
        throw IOException("Network error")
    }
    delay(1000)
}

supervisorScope

  • 原理supervisorScope创建了一个特殊的协程作用域,在这个作用域内启动的子协程不会因为其他子协程的异常而取消。当一个子协程抛出异常时,只有该子协程会被取消,其他子协程继续执行。异常会向上传播到supervisorScope的调用者,如果没有处理,最终会导致整个supervisorScope失败。
  • 使用场景:适用于多个子协程之间相对独立,单个子协程的失败不应影响其他子协程执行的场景。比如在批量处理任务时,每个任务作为一个子协程,个别任务失败不影响其他任务继续执行。
  • 示例
import kotlinx.coroutines.*

fun main() = runBlocking {
    supervisorScope {
        launch {
            delay(1000)
            println("Task 1 completed")
        }
        launch {
            throw IOException("Task 2 failed")
        }
        launch {
            delay(2000)
            println("Task 3 completed")
        }
    }
    println("All tasks are done (or failed)")
}

区别

  • 作用范围
    • try - catch作用于单个协程代码块内部,对局部代码异常进行捕获。
    • CoroutineExceptionHandler作用于整个CoroutineScope,处理该作用域内所有未捕获异常。
    • supervisorScope影响其内部启动的所有子协程间异常传播关系。
  • 异常处理方式
    • try - catch主动捕获异常并进行处理。
    • CoroutineExceptionHandler统一处理未捕获异常。
    • supervisorScope改变异常传播行为,防止子协程间相互影响。
  • 适用场景
    • try - catch适合处理已知特定异常。
    • CoroutineExceptionHandler适合全局统一处理未捕获异常。
    • supervisorScope适合多个相对独立子协程的场景。