Jetbrains在每一篇關于kotlin的文章中都提到了異步編程。但我不明白為什么它們被稱為異步? 根據我對kotlin coroutines的理解,這是一個帶有預置執行緒池的狀態機。我們有一個工人執行緒池和一個io執行緒池。對我來說,這只是一個多執行緒編程。如果我們向coroutine發送一個阻塞代碼,一個執行緒將被阻塞。如果我們使用async方法(來自默認的coroutines庫),它會給我們一種異步作業的錯覺,但這只不過是將 "作業 "發送到另一個執行緒。
另一個問題是,如果我們在coroutines中使用async io。但這是IO API的異步,而不是kotlin coroutines。與其他語言相比,Java的io async api不是很好(可能是錯的)。據我所知,.NET已經重建了他們的async api(作為IOCP),以使用C#任務,并且.NET有專門的執行緒池來等待應用程式的所有io,所以一個執行緒可以處理很多IO操作。但是kotlin的coroutines并沒有集成到java nio中,當我們從coroutine中呼叫nio時(無論是否有Dispatcher.IO),我們只是要求一個執行緒等待nio的資料。Java NIO有自己的執行緒池用于epoll或iocp,所以使用kotlin coroutine時,我們要求Dispatcher.IO給我們一個執行緒來等待NIO的結果,然后NIO實作創建自己的執行緒(池)來等待socket的資料,這就造成了開銷。我們現在有兩個執行緒(池)來等待,而不是一個執行緒(池)。
。因此,coroutines只是允許我們以一種簡單的方式將作業發送到另一個執行緒。如果你的api沒有用kotlin coroutines以異步方式實作,你就不能用一個執行緒同時做多個事情。
uj5u.com熱心網友回復:
他們談論異步編程是因為coroutines主要(但不限于)是作為一個庫來銷售的,以使異步編程更容易(主觀)。但正如你正確指出的,coroutines本身沒有任何異步。如果你在coroutine中執行阻塞的代碼,它將阻塞基礎執行緒。
但需要理解的是,只有在與掛起的函式結合時,才是真正有利的,在掛起的函式中,執行緒除了等待結果(回呼)之外,什么都不做。 另一個主要的優勢是,使用coroutines撰寫的異步代碼更容易撰寫和維護。例如,下面是使用回呼的異步呼叫
。fun callAPI(){
getToken{ token ->
auth(token){ authResult ->
doSomething(authResult){ finalResult ->
//使用最終結果。
}
}
}
}
這可以簡化為使用冠詞和懸空函式的如下內容
fun callAPI() = scope. launch(){
val token = getToken()
val authResult = auth(token)
val finalResult = doSomething(authResult)
}
現在,你有可能使用輪子來啟動多個長期運行的阻塞任務,但你不會看到任何優勢。因為在這種情況下,輪子只不過是一個高于執行緒的無用抽象。
uj5u.com熱心網友回復:
我將嘗試從不同的角度來看待這個問題。 Coroutines是基于懸浮函式的。暫停函式是異步的。
Coroutine 是一個狀態機的事實與此無關。一個狀態機可以被翻譯成一串異步函式,反之亦然。
與其將調度器視為 "執行緒池",不如將其視為一種反應器模式或事件回圈。是的,你可以封鎖一個事件回圈。然而,這并不意味著事件回圈不是異步的,也不意味著你應該這樣做。
你所說的 "異步作業的假象 "只有在你不在其中使用暫停函式時才是 "假象"。由于 Kotlin 代碼的很大一部分是暫停的(flow、Ktor 等),在現實中,你的大部分代碼將是有效的異步。
Java 的 NIO 具有與 Kotlin 不同的抽象:回呼。這些可以使用suspendCancellableCoroutine
最后一部分主要是錯誤的:
Coroutine只是允許我們以一種簡單的方式將作業發送到另一個執行緒。如果你的api沒有用kotlin coroutines以異步方式實作,你就不能用一個執行緒同時做多件事情。
一個調度員執行緒將在多個程式之間進行背景關系切換,除非其中一個程式是阻塞的:不使用任何暫停功能,并且執行 IO 或 CPU 密集型任務。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/329892.html
標籤:
上一篇:Nodejs異步函式未按順序運行
