Kotlin协程行业实践:异步更新资源函数是否符合规范?
Kotlin协程代码优化建议
你的代码能正常运行,但从Kotlin协程最佳实践和行业标准来看,有几个关键优化点:
1. 替换runBlocking为挂起函数
runBlocking仅适用于main函数或测试场景,用来衔接阻塞代码与协程。业务方法应声明为挂起函数,避免不必要的线程阻塞,契合协程协作式调度的设计:
override suspend fun update(resourceCommand: UpdateResourceCommand): List<Resource> { return resourceCommand.resources.map { async { val resource = load(it) resource.isProtected = it.isProtected resource } }.awaitAll() }
2. 限制并发数量
若待处理的资源数量较多,无限制创建async协程可能耗尽数据库连接池或线程资源。建议用flow的flatMapMerge控制并发数:
override suspend fun update(resourceCommand: UpdateResourceCommand): List<Resource> = coroutineScope { resourceCommand.resources.asFlow() .flatMapMerge(concurrency = 10) { cmdRes -> // 根据系统配置调整并发数 flow { val resource = load(cmdRes) resource.isProtected = cmdRes.isProtected emit(resource) } } .toList() }
3. 避免直接修改加载的对象
直接修改load返回的Resource实例可能引发意外副作用(比如ORM框架自动跟踪实体变更导致误更新)。推荐通过复制创建新对象:
// 假设Resource是数据类 async { val resource = load(it) resource.copy(isProtected = it.isProtected) }
若Resource不是数据类,需手动实现复制逻辑生成新实例。
4. 为IO操作指定调度器
如果load是阻塞式数据库查询等IO操作,应放在Dispatchers.IO调度器执行,避免占用默认调度器的线程:
async(Dispatchers.IO) { val resource = load(it) resource.copy(isProtected = it.isProtected) }
优化后完整示例
override suspend fun update(resourceCommand: UpdateResourceCommand): List<Resource> = coroutineScope { resourceCommand.resources.asFlow() .flatMapMerge(concurrency = 10) { cmdRes -> flow(Dispatchers.IO) { val dbResource = load(cmdRes) emit(dbResource.copy(isProtected = cmdRes.isProtected)) } } .toList() }
内容的提问来源于stack exchange,提问作者user15941734
相关产品推荐
相关产品推荐

