MST

星途 面试题库

面试题:Kotlin协程中的异常处理机制

在Kotlin协程中,异常处理与传统线程有很大不同,请详细说明如何在协程内部以及协程之间正确处理异常,比如使用try - catch块、coroutineExceptionHandler等方式,并说明不同处理方式的适用场景。
46.4万 热度难度
编程语言Kotlin

知识考点

AI 面试

面试题答案

一键面试

在协程内部处理异常

  1. 使用try - catch块
    • 示例代码
import kotlinx.coroutines.*

fun main() = runBlocking {
    try {
        val result = withContext(Dispatchers.Default) {
            throw RuntimeException("模拟异常")
            "任务完成"
        }
        println(result)
    } catch (e: Exception) {
        println("捕获到异常: $e")
    }
}
- **适用场景**:适用于需要在特定的协程代码块中,对可能出现的异常进行精细控制的场景。例如,当某个协程执行特定的业务逻辑,而你希望在该业务逻辑出错时进行相应处理,比如记录日志、进行补偿操作等。

2. 使用coroutineExceptionHandler - 示例代码

import kotlinx.coroutines.*

val handler = CoroutineExceptionHandler { _, exception ->
    println("全局异常处理: $exception")
}

fun main() = runBlocking {
    GlobalScope.launch(handler) {
        throw RuntimeException("模拟异常")
    }
    delay(1000)
}
- **适用场景**:适用于处理多个协程或整个应用程序范围内的异常。比如在一个大型项目中,多个地方启动了协程,希望有一个统一的异常处理机制来记录日志、通知用户等,而不需要在每个协程中都写try - catch块。

在协程之间处理异常

  1. 父协程与子协程关系中的异常处理
    • 默认行为:在Kotlin协程中,子协程抛出的未处理异常会向上传播到父协程,导致父协程也会异常结束。
    • 示例代码
import kotlinx.coroutines.*

fun main() = runBlocking {
    val job = launch {
        launch {
            throw RuntimeException("子协程异常")
        }
    }
    try {
        job.join()
    } catch (e: Exception) {
        println("父协程捕获到异常: $e")
    }
}
- **适用场景**:当子协程的异常会影响到父协程的整体逻辑时,父协程需要捕获并处理子协程的异常,以决定后续的操作,比如是否要继续执行其他子协程或进行整体的清理工作。

2. 使用supervisorJob - 示例代码

import kotlinx.coroutines.*

fun main() = runBlocking {
    val supervisor = SupervisorJob()
    val scope = CoroutineScope(supervisor + Dispatchers.Default)
    scope.launch {
        throw RuntimeException("子协程异常")
    }
    scope.launch {
        println("另一个子协程继续执行")
    }
    delay(1000)
}
- **适用场景**:当希望子协程之间相互独立,一个子协程的异常不影响其他子协程的执行时,使用supervisorJob。比如在一个并行处理多个任务的场景中,某个任务失败不应导致其他任务中断。