面试题答案
一键面试- 使用
try - catch
块- 在Kotlin协程中,可以在
runBlocking
、coroutineScope
等函数内部使用try - catch
块来捕获协程执行过程中抛出的异常。coroutineScope
会等待其内部所有协程执行完毕,并且如果任何一个协程抛出异常,整个coroutineScope
块会终止并抛出该异常。 - 示例代码:
- 在Kotlin协程中,可以在
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
coroutineScope {
launch {
delay(100)
println("协程1正在执行")
}
launch {
delay(200)
println("协程2正在执行")
throw RuntimeException("协程2抛出异常")
}
}
} catch (e: Exception) {
println("捕获到异常: $e")
}
}
- 使用
CoroutineExceptionHandler
CoroutineExceptionHandler
可以用于全局处理未捕获的协程异常。它可以定义在CoroutineScope
的coroutineContext
中。- 示例代码:
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, exception ->
println("全局异常处理: $exception")
}
fun main() = runBlocking {
coroutineScope {
launch(handler) {
delay(100)
println("协程1正在执行")
}
launch(handler) {
delay(200)
println("协程2正在执行")
throw RuntimeException("协程2抛出异常")
}
}
}
- 确保资源不泄漏
- 对于需要释放的资源(如文件句柄、数据库连接等),可以使用
use
函数(针对实现了AutoCloseable
接口的资源)。在协程异常处理时,这些资源会被正确关闭。 - 示例代码:
- 对于需要释放的资源(如文件句柄、数据库连接等),可以使用
import java.io.File
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
coroutineScope {
launch {
File("test.txt").use { file ->
file.writeText("测试内容")
delay(100)
println("协程1写入文件完毕")
}
}
launch {
delay(200)
println("协程2正在执行")
throw RuntimeException("协程2抛出异常")
}
}
} catch (e: Exception) {
println("捕获到异常: $e")
}
}
在上述代码中,File("test.txt").use
块会确保在协程执行完毕(无论是正常结束还是因异常终止)时,文件资源被正确关闭,避免资源泄漏。
通过结合try - catch
和CoroutineExceptionHandler
,并合理使用资源管理机制,可以确保在Kotlin协程结构化并发编程中,正确处理异常,避免资源泄漏并向调用者返回恰当的错误信息。