![](/img/trans.png)
[英]Best way to call suspend coroutine from Executor(ThreadPoolExecutor)
[英]Correct way to suspend coroutine until Task<T> is complete
我最近潛入Kotlin協同程序因為我使用了很多Google的庫,所以大部分工作都是在Task類中完成的
目前我正在使用此擴展來暫停協程
suspend fun <T> awaitTask(task: Task<T>): T = suspendCoroutine { continuation ->
task.addOnCompleteListener { task ->
if (task.isSuccessful) {
continuation.resume(task.result)
} else {
continuation.resumeWithException(task.exception!!)
}
}
}
但最近我見過這樣的用法
suspend fun <T> awaitTask(task: Task<T>): T = suspendCoroutine { continuation ->
try {
val result = Tasks.await(task)
continuation.resume(result)
} catch (e: Exception) {
continuation.resumeWithException(e)
}
}
有什么區別,哪一個是正確的?
UPD:第二個例子不起作用,idk為什么
傳遞給suspendCoroutine { ... }
的代碼塊不應該阻塞正在調用它的線程,允許協程被掛起。 這樣,實際線程可以用於其他任務。 這是一個關鍵功能,允許Kotlin協程擴展並在單個UI線程上運行多個協同程序。
第一個例子是正確的,因為它調用task.addOnCompleteListener
(參見docs) (它只是添加一個監聽器並立即返回。這就是第一個正常工作的原因。
第二個示例使用Tasks.await(task)
(請參閱docs)來阻止調用它的線程,並且在任務完成之前不會返回,因此它不允許協程正確掛起。
您的第二個示例是更傳統的阻止功能。
在典型的Java多線程世界中,您使用類似的函數來阻塞線程,直到結果返回。
同樣在典型的Java中,有一種稱為Reactive programming的新范例,它允許您在結果返回之前避免阻塞線程。 您可以提供一個在結果到達時執行的第一類函數,而不是僅僅等待結果。 這樣,暫停時沒有留下線程; 相反,只有一個新事件附加到運行長操作的線程上,當操作完成時,該事件將觸發。
阻塞:
Thread one: --* . . . ./---
Thread two: \------*
反應:
Thread one: --* (now free)
Thread two: \-------*---
如果你研究反應式編程,你會發現更好的解釋,深入探討。
回到你的問題,這兩種看似相同的方式是Java范式轉變的結果。 當然,由於我們與協程在這里工作,我們不必擔心,阻斷問題都沒有; 語言通過暫停而不是阻止來處理它。 因此,反應性編程的許多優點在語言層面上得到了解決。
然而 ,范式仍然有其優點,所以即使它不像其他地方那樣嚴格必要,看到人們繼續以這種模式工作也是有道理的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.