You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Retrofit配合协程发起网络请求的线程安全性及优化方案咨询

关于线程安全性的问题解答

你的原有认知存在错误,当前实现不具备线程安全性,风险点如下:

  • Kotlin默认创建的普通对象、集合都没有内置线程安全保障,你使用的mutableListOf底层是Java的ArrayList,属于非线程安全集合,多线程并发调用add方法时,可能出现元素丢失、数组越界、长度统计异常等问题。
  • 第三方库内部使用Dispatchers.IO调度网络请求,回调方法onResult会在IO线程池的不同子线程执行,不会自动为你的handler实例加锁,完全可能出现多个请求同时执行add操作、同时读取列表长度的竞态场景,极端情况下会出现结果处理逻辑被多次触发、结果列表元素缺失的问题。

更优的业务实现方案

推荐使用协程的回调转挂起能力,将第三方库的回调式API改造为挂起函数,再通过协程并发原语统一管理请求和结果,完全规避手动维护集合、计数的线程安全问题,实现代码如下:

  1. 封装回调API为挂起函数
suspend fun checkUserSuspend(userId: String): UserCheckResult? = suspendCoroutine { continuation ->
    checkUser(userId, object : UserCheckResultHandler {
        override fun onResult(userCheckResult: UserCheckResult?) {
            continuation.resume(userCheckResult)
        }
    })
}
  1. 并发请求并统一收集结果
val userList: List<String> = getUsers() ?: return
// 可根据业务场景替换为对应的协程作用域,如viewModelScope、lifecycleScope
coroutineScope {
    // 批量创建异步请求任务
    val requestTasks = userList.map { userId ->
        async(Dispatchers.IO) {
            checkUserSuspend(userId)
        }
    }
    // 等待所有请求完成,过滤无效空结果
    val allValidResults = requestTasks.awaitAll().filterNotNull()
    // 统一处理全部结果
    doSomethingWithResultList(allValidResults)
    print("SUCCESS")
}

该方案的优势:

  • 无需手动操作非线程安全集合、无需自行计数判断请求完成状态,协程框架会保证结果收集的安全性,awaitAll会自动等待所有任务执行完毕。
  • 可灵活拓展超时、取消、异常处理逻辑,比如配置单个请求超时时间、部分请求失败时取消所有剩余任务等。

如果要兼容原有回调实现,也可以临时将结果列表替换为线程安全实现,比如val userCheckResultList = Collections.synchronizedList(mutableListOf<UserCheckResult>()),同时给onResult的逻辑加同步锁,但该方案的可维护性、扩展性远低于协程原生方案。

内容的提问来源于stack exchange,提问作者Igor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 05:15:01