面试题答案
一键面试-
使用
try - catch
块捕获异常: 在Kotlin协程中,可以在try - catch
块内启动协程,这样当协程抛出异常时,catch
块可以捕获到异常。 同时,为了避免其他子协程无意义的继续执行,可以使用Job
来管理协程的生命周期,当一个子协程出错时,取消其他相关的子协程。 对于资源释放,可以使用finally
块来确保资源无论是否发生异常都能正确释放。 -
代码示例:
import kotlinx.coroutines.*
// 模拟需要释放的资源
class Resource : AutoCloseable {
init {
println("Resource created")
}
override fun close() {
println("Resource closed")
}
}
fun main() = runBlocking {
val job = Job()
val scope = CoroutineScope(Dispatchers.Default + job)
val resource = Resource()
try {
val deferred1 = scope.async {
// 模拟第一个子协程任务
delay(1000)
println("Sub - coroutine 1 is running")
throw RuntimeException("Sub - coroutine 1 error")
}
val deferred2 = scope.async {
// 模拟第二个子协程任务
delay(1500)
println("Sub - coroutine 2 is running")
}
deferred1.await()
deferred2.await()
} catch (e: Exception) {
println("Caught exception: $e")
job.cancel() // 取消其他子协程
} finally {
resource.close() // 释放资源
}
}
- 代码说明:
- 首先定义了一个
Resource
类,实现了AutoCloseable
接口,用于模拟需要释放的资源。 - 在
main
函数中,使用runBlocking
创建了一个顶层协程。 - 创建了一个
Job
对象job
,并基于它创建了一个CoroutineScope
对象scope
,这个scope
的生命周期与job
相关联。 - 在
try
块中启动了两个子协程deferred1
和deferred2
。deferred1
故意抛出一个异常来模拟错误情况。 deferred1.await()
和deferred2.await()
用于等待子协程执行完成。如果deferred1
抛出异常,await()
会将异常传递出来。- 在
catch
块中,捕获到异常后打印异常信息,并调用job.cancel()
取消其他子协程(这里就是deferred2
),避免其无意义的继续执行。 - 在
finally
块中,调用resource.close()
释放资源,确保无论是否发生异常,资源都能被正确释放。
- 首先定义了一个