將有關使用協程啟動網路請求的執行緒安全性的所有資訊放在一起時,我仍然有點麻煩。
假設我們有以下用例,有一個我們獲得的用戶串列,對于每個用戶,我將做一些特定的檢查,這些檢查必須通過對 API 的網路請求運行,給我一些關于這個用戶的資訊.
userCheck 發生在一個庫中,它不公開掛起函式,而是仍然使用回呼。在這個庫中,我看到過這樣的代碼來啟動每個網路請求:
internal suspend fun <T> doNetworkRequest(request: suspend () -> Response<T>): NetworkResult<T> {
return withContext(Dispatchers.IO) {
try {
val response = request.invoke()
...
根據檔案,Dispatchers.IO 可以使用多個執行緒來執行代碼,而且請求函式只是一個來自 Retrofit API 的函式。
所以我所做的是為每個用戶發起請求,并使用單個 resultHandler 物件,它將結果添加到串列中并檢查結果串列的長度是否等于用戶串列的長度,如果是,則所有userChecks 已經完成,我知道我可以對結果做一些事情,這些結果需要一起回傳。
val userList: List<String>? = getUsers()
val userCheckResultList = mutableListOf<UserCheckResult>()
val handler = object : UserCheckResultHandler {
override fun onResult(
userCheckResult: UserCheckResult?
) {
userCheckResult?.let {
userCheckResultList.add(
it
)
}
if (userCheckResultList.size == userList?.size) {
doSomethingWithResultList()
print("SUCCESS")
}
}
}
userList?.forEach {
checkUser(it, handler)
}
我的問題是:這個實作執行緒安全嗎?據我所知,Kotlin 物件應該是執行緒安全的,但我收到反饋說這可能不是最好的實作:D
但理論上,即使請求以異步方式和多個同時啟動,一次只有一個可以訪問運行結果處理程式的執行緒的鎖,并且不會出現競爭條件或向物件添加項的問題列出并比較大小。
我錯了嗎?有沒有辦法以更好的方式處理這種情況?
uj5u.com熱心網友回復:
如果您并行執行多個請求 - 它不是。List不是執行緒安全的。但這很簡單。創建一個Mutex物件,然后將您的操作鎖定在串列中,如下所示:
val lock = Mutex()
val userList: List<String>? = getUsers()
val userCheckResultList = mutableListOf<UserCheckResult>()
val handler = object : UserCheckResultHandler {
override fun onResult(
userCheckResult: UserCheckResult?
) {
lock.withLock {
userCheckResult?.let {
userCheckResultList.add(
it
)
}
if (userCheckResultList.size == userList?.size) {
doSomethingWithResultList()
print("SUCCESS")
}
}
}
}
userList?.forEach {
checkUser(it, handler)
}
我必須補充一點,整個解決方案看起來很hacky。我會完全走另一條路。運行所有async { // network request }包含將回傳Deferred物件的請求的請求。將此物件添加到某個串列中。之后使用awaitAll(). 像那樣:
val jobs = mutableListOf<Job>()
userList?.forEach {
// i assume checkUser is suspendable here
jobs = async { checkUser(it, handler) }
}
// wait for all requests
jobs.awaitAll()
// After that you can access all results like this:
val resultOfJob0 = jobs[0].getCompleted()
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/330290.html
