精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Kotlin協程實戰進階之筑基篇2

jf_78858299 ? 來源:小余的自習室 ? 作者:蘇火火 ? 2023-05-30 16:25 ? 次閱讀
launch 創建子協程

通過launch在一個協程中啟動子協程,可以根據業務需求創建一個或多個子協程:

fun launchTest3() {
    print("start")
    GlobalScope.launch {
        delay(1000)
        print("CoroutineScope.launch")

        //在協程內創建子協程
        launch {
            delay(1500)//1.5秒無阻塞延遲(默認單位為毫秒)
            print("launch 子協程")
        }
    }
    print("end")
}

打印數據如下:

圖片

launch3.gif

async

async類似于launch,都是創建一個不會阻塞當前線程的新的協程。它們區別在于:async的返回是Deferred對象,可通過Deffer.await()等待協程執行完成并獲取結果,而 launch 不行。常用于并發執行-同步等待和獲取返回值的情況。

public fun  CoroutineScope.async(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T
): Deferred
  • context:?協程的上下文,同launch
  • start: ?協程啟動模式,同launch
  • block:??協程代碼,同launch
  • Deferred:?協程構建函數的返回值,繼承自Job,一個有結果的Job,可通過Deffer.await()等待協程執行完成并獲取結果。
await 獲取返回值
//獲取返回值
fun asyncTest1() {
    print("start")
    GlobalScope.launch {
        val deferred: Deferred<String> = async {
            //協程將線程的執行權交出去,該線程繼續干它要干的事情,到時間后會恢復至此繼續向下執行
            delay(2000)//2秒無阻塞延遲(默認單位為毫秒)
            print("asyncOne")
            "HelloWord"//這里返回值為HelloWord
        }

        //等待async執行完成獲取返回值,此處并不會阻塞線程,而是掛起,將線程的執行權交出去
        //等到async的協程體執行完畢后,會恢復協程繼續往下執行
        val result = deferred.await()
        print("result == $result")
    }
    print("end")
}

上面例子中返回對象Deferred, 通過函數await()獲取結果值。打印數據如下:

圖片

async1.gif

注意:await() 不能在協程之外調用,因為它需要掛起直到計算完成,而且只有協程可以以非阻塞的方式掛起。所以把它放到協程中。

async 并發

當在協程作用域中使用async函數時可以創建并發任務:

fun asyncTest2() {
    print("start")
    GlobalScope.launch {
        val time = measureTimeMillis {//計算執行時間
            val deferredOne: Deferred<Int> = async {
                delay(2000)
                print("asyncOne")
                100//這里返回值為100
            }

            val deferredTwo: Deferred<Int> = async {
                delay(3000)
                print("asyncTwo")
                200//這里返回值為200
            }

            val deferredThr: Deferred<Int> = async {
                delay(4000)
                print("asyncThr")
                300//這里返回值為300
            }

            //等待所有需要結果的協程完成獲取執行結果
            val result = deferredOne.await() + deferredTwo.await() + deferredThr.await()
            print("result == $result")
        }
        print("耗時 $time ms")
    }
    print("end")
}

打印數據如下:

圖片

async2.gif

上面的代碼就是一個簡單的并發示例,async是不阻塞線程的,也就是說上面三個async{}異步任務是同時進行的。通過await()方法可以拿到async協程的執行結果,可以看到兩個協程的總耗時是遠少于9秒的,總耗時基本等于耗時最長的協程。

1.Deferred集合還可以使用awaitAll()等待全部完成;

2.如果Deferred不執行await()async內部拋出的異常不會被logCattryCatch捕獲, 但是依然會導致作用域取消和異常崩潰; 但當執行await時異常信息會重新拋出。

3.惰性并發,如果將async函數中的啟動模式設置為CoroutineStart.LAZY懶加載模式時則只有調用Deferred對象的await時(或者執行async.satrt())才會開始執行異步任務。

launch構建器適合執行 "一勞永逸" 的工作,意思就是說它可以啟動新協程而不需要結果返回;async構建器可啟動新協程并允許您使用一個名為await的掛起函數返回result,并且支持并發。另外launchasync之間的很大差異是它們對異常的處理方式不同。如果使用async作為最外層協程的開啟方式,它期望最終是通過調用 await 來獲取結果 (或者異常),所以默認情況下它不會拋出異常。這意味著如果使用 async啟動新的最外層協程,而不使用await,它會靜默地將異常丟棄。

2.Job & Deferred

反觀線程,java平臺上很明確地給出了線程的類型Thread,我們也需要一個這樣的類來描述協程,它就是Job。它的API設計與Java的Thread殊途同歸。

Job

Job 是協程的句柄。如果把門和門把手比作協程和Job之間的關系,那么協程就是這扇門,Job就是門把手。意思就是可以通過Job實現對協程的控制和管理。

從上面可以知道Joblaunch構建協程返回的一個協程任務,完成時是沒有返回值的。可以把Job看成協程對象本身,封裝了協程中需要執行的代碼邏輯,協程的操作方法都在Job身上。Job具有生命周期并且可以取消,它也是上下文元素,繼承自CoroutineContext

這里列舉Job幾個比較有用的函數:

public interface Job : CoroutineContext.Element {
    //活躍的,是否仍在執行
    public val isActive: Boolean

    //啟動協程,如果啟動了協程,則為true;如果協程已經啟動或完成,則為false
    public fun start(): Boolean

    //取消Job,可通過傳入Exception說明具體原因
    public fun cancel(cause: CancellationException? = null)

    //掛起協程直到此Job完成
    public suspend fun join()

    //取消任務并等待任務完成,結合了[cancel]和[join]的調用
    public suspend fun Job.cancelAndJoin() 

    //給Job設置一個完成通知,當Job執行完成的時候會同步執行這個函數
    public fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle
}

Thread相比,Job同樣有join(),調用時會掛起(線程的join()則會阻塞線程),直到協程完成;它的cancel()可以類比Threadinterrupt(),用于取消協程;isActive則是可以類比ThreadisAlive(),用于查詢協程是否仍在執行。

Job是一個接口類型,它具有以下三種狀態:

狀態 說明
isActive 活躍的。當Job處于活動狀態時為true,如果Job已經開始,但還沒有完成、也沒有取消或者失敗,則是處于active狀態。
isCompleted 已完成。當Job由于任何原因完成時為true,已取消、已失敗和已完成Job都是被視為完成狀態。
isCancelled 已退出。當Job由于任何原因被取消時為true,無論是通過顯式調用cancel或這因為它已經失敗亦或者它的子或父被取消,都是被視為已退出狀態。

這里模擬一個無限循環的協程,當協程是活躍狀態時每秒鐘打印兩次消息,1.2秒后取消協程:

fun jobTest() = runBlocking {
    val startTime = System.currentTimeMillis()
    val job = launch(Dispatchers.Default){
        var nextPrintTime = startTime
        var i = 0

        while (isActive) {//當job是活躍狀態繼續執行
            if (System.currentTimeMillis() >= nextPrintTime) {//每秒鐘打印兩次消息
                print("job: I'm sleeping ${i++} ...")
                nextPrintTime += 500
            }
        }
    }

    delay(1200)//延遲1.2s
    print("等待1.2秒后")


    //job.join()
    //job.cancel()
    job.cancelAndJoin()//取消任務并等待任務完成
    print("協程被取消并等待完成")
}

join()是一個掛起函數,它需要等待協程的執行,如果協程尚未完成,join()立即掛起,直到協程完成;如果協程已經完成,join()不會掛起,而是立即返回。打印數據如下:

圖片

join.gif

Job 還可以有層級關系,一個Job可以包含多個子Job,當父Job被取消后,所有的子Job也會被自動取消;當子Job被取消或者出現異常后父Job也會被取消。具有多個子 Job 的父Job 會等待所有子Job完成(或者取消)后,自己才會執行完成。

總的來說:它的作用是Job實例作為協程的唯一標識,用于處理協程,并且負責管理協程的生命周期。

Deferred

Deferred繼承自Job,具有與Job相同的狀態機制。它是async構建協程返回的一個協程任務,可通過調用await()方法等待協程執行完成并獲取結果。不同的是Job沒有結果值,Deffer有結果值。

public interface Deferred<out T> : Job {
    //等待協程執行完成并獲取結果
    public suspend fun await(): T
}
  • await():?等待協程執行完畢并返回結果,如果異常結束則會拋出異常;如果協程尚未完成,則掛起直到協程執行完成。
  • T:????這里多了一個泛型參數T,它表示返回值類型,通過await()函數可以拿到這個返回值。

上面已有Deferred代碼演示,這里就不再重復實踐。

3.作用域

通常我們提到的,都是用來描述范圍的,既有約束作用又有提供額外能力的作用。

協程作用域(CoroutineScope)其實就是為協程定義的作用范圍 ,為了確保所有的協程都會被追蹤,Kotlin 不允許在沒有使用CoroutineScope的情況下啟動新的協程。CoroutineScope可被看作是一個具有超能力的ExecutorService的輕量級版本。它能啟動新的協程,同時這個協程還具備上面所說的suspendresume的優勢。

每個協程生成器launchasync等都是CoroutineScope的擴展,并繼承了它的coroutineContext自動傳播其所有元素和取消。協程作用域本質是一個接口:

public interface CoroutineScope {
    //此域的上下文。Context被作用域封裝,用于在作用域上擴展的協程構建器的實現。
    public val coroutineContext: CoroutineContext
}

因為 啟動協程需要作用域 ,但是作用域又是在協程創建過程中產生的,這似乎是一個“先有雞后有蛋還是先有蛋后有雞”的問題。

常用作用域

官方庫給我們提供了一些作用域可以直接來使用:

  • runBlocking:頂層函數,它的第二個參數為接收者是CoroutineScope的函數字面量,可啟動協程。但是它會阻塞當前線程,主要用于測試。
  • GlobalScope:全局協程作用域,通過GlobalScope創建的協程不會有父協程,可以把它稱為根協程。它啟動的協程的生命周期只受整個應用程序的生命周期的限制,且不能取消,在運行時會消耗一些內存資源,這可能會導致內存泄露,所以仍不適用于業務開發。
  • coroutineScope:創建一個獨立的協程作用域,直到所有啟動的協程都完成后才結束自身。它是一個掛起函數,需要運行在協程內或掛起函數內。當這個作用域中的任何一個子協程失敗時,這個作用域失敗,所有其他的子程序都被取消。為并行分解工作而設計的。
  • supervisorScope:與coroutineScope類似,不同的是子協程的異常不會影響父協程,也不會影響其他子協程。(作用域本身的失敗(在block或取消中拋出異常)會導致作用域及其所有子協程失敗,但不會取消父協程。)
  • MainScope:為UI組件創建主作用域。一個頂層函數,上下文是SupervisorJob() + Dispatchers.Main,說明它是一個在主線程執行的協程作用域,通過cancel對協程進行取消。推薦使用。
fun scopeTest() {
    //創建一個根協程
    GlobalScope.launch {//父協程
        launch {//子協程
            print("GlobalScope的子協程")
        }
        launch {//第二個子協程
            print("GlobalScope的第二個子協程")
        }
    }

    //為UI組件創建主作用域
    val mainScope = MainScope()
    mainScope.launch {//啟動協程
        //todo
    }
}

注意:MainScope作用域的好處就是方便地綁定到UI組件的聲明周期上,在Activity銷毀的時候mainScope.cancel()取消其作用域。

Lifecycle的協程支持

Android 官方對協程的支持是非常友好的,KTX 為 Jetpack 的Lifecycle相關組件提供了已經綁定UV聲明周期的作用域供我們直接使用:

  • lifecycleScopeLifecycle Ktx庫提供的具有生命周期感知的協程作用域,與Lifecycle綁定生命周期,生命周期被銷毀時,此作用域將被取消。會與當前的UI組件綁定生命周期,界面銷毀時該協程作用域將被取消,不會造成協程泄漏,推薦使用。
  • viewModelScope:與lifecycleScope類似,與ViewModel綁定生命周期,當ViewModel被清除時,這個作用域將被取消。推薦使用。

build.gradle添加Lifecycle相應基礎組件后,再添加以下組件即可:

// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
// 只有Lifecycles(沒有 ViewModel 和 LiveData)
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"

因為Activity 實現了LifecycleOwner這個接口,而lifecycleScope則正是它的拓展成員,可以在Activity中直接使用lifecycleScope協程實例:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btn_data.setOnClickListener {
            lifecycleScope.launch {//使用lifecycleScope創建協程
                //協程執行體
            }
        }
    }
}

ViewModel中使用創建協程:

class MainViewModel : ViewModel() {
    fun getData() {
        viewModelScope.launch {//使用viewModelScope創建協程
            //執行協程
        }
    }
}

注意:VIewModel 的作用域會在它的 clear 函數調用時取消。

分類和行為規則

官方框架在實現復合協程的過程中也提供了作用域,主要用于明確父子關系,以及取消或者異常處理等方面的傳播行為。該作用域分為以下三種:

  • 頂級作用域 :沒有父協程的協程所在的作用域為頂級作用域。
  • 協同作用域 :協程中啟動新的協程,新協程為所在協程的子協程,這種情況下,子協程所在的作用域默認為協同作用域。此時子協程拋出的未捕獲異常,都將傳遞給父協程處理,父協程同時也會被取消。
  • 主從作用域 :與協同作用域在協程的父子關系上一致,區別在于,處于該作用域下的協程出現未捕獲的異常時,不會將異常向上傳遞給父協程。除了三種作用域中提到的行為以外,父子協程之間還存在以下規則:
  • 父協程被取消,則所有子協程均被取消。由于協同作用域和主從作用域中都存在父子協程關系,因此此條規則都適用。
  • 父協程需要等待子協程執行完畢之后才會最終進入完成狀態,不管父協程自身的協程體是否已經執行完。
  • 子協程會繼承父協程的協程上下文中的元素,如果自身有相同key的成員,則覆蓋對應的key,覆蓋的效果僅限自身范圍內有效。

4.調度器

在上面介紹協程概念的時候,協程的掛起與恢復在哪掛起,什么時候恢復,為什么能切換線程,這因為調度器的作用:它確定相應的協程使用那些線程來執行。

CoroutineDispatcher調度器指定指定執行協程的目標載體,它確定了相關的協程在哪個線程或哪些線程上執行。可以將協程限制在一個特定的線程執行,或將它分派到一個線程池,亦或是讓它不受限地運行。

協程需要調度的位置就是掛起點的位置,只有當掛起點正在掛起的時候才會進行調度,實現調度需要使用協程的攔截器。調度的本質就是解決掛起點恢復之后的協程邏輯在哪里運行的問題。調度器也屬于協程上下文一類,它繼承自攔截器:

public abstract class CoroutineDispatcher :
    AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {

    //詢問調度器是否需要分發
    public open fun isDispatchNeeded(context: CoroutineContext): Boolean = true

    //將可運行塊的執行分派到給定上下文中的另一個線程上。這個方法應該保證給定的[block]最終會被調用。
    public abstract fun dispatch(context: CoroutineContext, block: Runnable)

    //返回一個continuation,它封裝了提供的[continuation],攔截了所有的恢復。
    public final override fun  interceptContinuation(continuation: Continuation<T>): Continuation

它是所有協程調度程序實現擴展的基類(我們很少會自己自定義調度器)。可以使用newSingleThreadContextnewFixedThreadPoolContext創建私有線程池。也可以使用asCoroutineDispatcher擴展函數將任意java.util.concurrent.Executor轉換為調度程序。

調度器模式

Kotlin 提供了四個調度器,您可以使用它們來指定應在何處運行協程:

調度器模式 說明 適用場景
Dispatchers.Default 默認調度器,非主線程。CPU密集型任務調度器,適合處理后臺計算。 通常處理一些單純的計算任務,或者執行時間較短任務比如:Json的解析,數據計算等。
Dispatchers.Main UI調度器, Andorid 上的主線程。 調度程序是單線程的,通常用于UI交互,刷新等。
Dispatchers.Unconfined 一個不局限于任何特定線程的協程調度程序,即非受限調度器。 子協程切換線程代碼會運行在原來的線程上,協程在相應的掛起函數使用的任何線程中繼續。
Dispatchers.IO IO調度器,非主線程,執行的線程是IO線程。 適合執行IO相關操作,比如:網絡處理,數據庫操作,文件讀寫等。

所有的協程構造器(如launchasync)都接受一個可選參數,即 CoroutineContext ,該參數可用于顯式指定要創建的協程和其它上下文元素所要使用的CoroutineDispatcher

fun dispatchersTest() {
    //創建一個在主線程執行的協程作用域
    val mainScope = MainScope()
    mainScope.launch {
        launch(Dispatchers.Main) {//在協程上下參數中指定調度器
            print("主線程調度器")
        }
        launch(Dispatchers.Default) {
            print("默認調度器")
        }
        launch(Dispatchers.Unconfined) {
            print("任意調度器")
        }
        launch(Dispatchers.IO) {
            print("IO調度器")
        }
    }
}

打印數據如下:

圖片

image.png

withContext

在 Andorid 開發中,我們常常在子線程中請求網絡獲取數據,然后切換到主線程更新UI。官方為我們提供了一個withContext頂級函數,在獲取數據函數內,調用withContext(Dispatchers.IO)來創建一個在IO線程池中運行的塊。您放在該塊內的任何代碼都始終通過IO調度器執行。由于withContext本身就是一個suspend函數,它會使用協程來保證主線程安全。

//用給定的協程上下文調用指定的掛起塊,掛起直到它完成,并返回結果。
public suspend fun  withContext(
    context: CoroutineContext,
    block: suspend CoroutineScope.() -> T
): T
  • context:?協程的上下文,同上(調度器也屬于上下文一類)。
  • block:??協程執行體,同上。block中的代碼會被調度到上面指定的調度器上執行,并返回結果值。

這個函數會使用新指定的上下文的dispatcher,將block的執行轉移到指定的線程中。它會返回結果, 可以和當前協程的父協程存在交互關系, 主要作用為了來回切換調度器

GlobalScope.launch(Dispatchers.Main) {//開始協程:主線程
    val result: User = withContext(Dispatchers.IO) {//網絡請求(IO 線程)
        userApi.getUserSuspend("FollowExcellence")
    }
    tv_title.text = result.name //更新 UI(主線程)
}

在主線程中啟動一個協程,然后再通過withContext(Dispatchers.IO)調度到IO線程上去做網絡請求,獲取結果返回后,主線程上的協程就會恢復繼續執行,完成UI的更新。

由于withContext可讓在不引入回調的情況下控制任何代碼行的線程池,因此可以將其應用于非常小的函數,如從數據庫中讀取數據或執行網絡請求。一種不錯的做法是使用withContext來確保每個函數都是主線程安全的,那么可以從主線程調用每個函數。調用方也就無需再考慮應該使用哪個線程來執行函數了。您可以使用外部 withContext來讓 Kotlin 只切換一次線程,這樣可以在多次調用的情況下,以盡可能避免了線程切換所帶來的性能損失。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Android
    +關注

    關注

    12

    文章

    3926

    瀏覽量

    127158
  • JAVA
    +關注

    關注

    19

    文章

    2960

    瀏覽量

    104562
  • 編程
    +關注

    關注

    88

    文章

    3596

    瀏覽量

    93609
  • ui
    ui
    +關注

    關注

    0

    文章

    204

    瀏覽量

    21342
  • kotlin
    +關注

    關注

    0

    文章

    60

    瀏覽量

    4185
收藏 人收藏

    評論

    相關推薦

    談談的那些事兒

    隨著異步編程的發展以及各種并發框架的普及,作為一種異步編程規范在各類語言中地位逐步提高。我們不單單會在自己的程序中使用,各類框架如fastapi,aiohttp等也都是基于異步
    的頭像 發表于 01-26 11:36 ?1092次閱讀
    談談<b class='flag-5'>協</b><b class='flag-5'>程</b>的那些事兒

    Python中的多核CPU共享數據詳解

    又稱微線程,coroutne,是一種用戶態的輕量級線程。通俗點講就是周末我在家里休息,假如我先洗漱,再煮飯,再下載電影看會很慢,用了
    的頭像 發表于 12-07 10:23 ?6585次閱讀
    Python中的多核CPU共享數據<b class='flag-5'>之</b><b class='flag-5'>協</b><b class='flag-5'>程</b>詳解

    Python自動化運維函數賦值過程

    的優點:(1)無需線程上下文切換的開銷,避免了無意義的調度,由此可以提高性能(但也因此,程序員必須自己承擔調度的責任,同時,
    的頭像 發表于 03-18 11:22 ?3711次閱讀

    關于C++ 20最全面詳解

    花了一兩周的時間后,我想寫寫 C++20 的基本用法,因為 C++ 的讓我感到很奇怪,寫一個
    的頭像 發表于 04-12 11:10 ?1.3w次閱讀
    關于C++ 20<b class='flag-5'>協</b><b class='flag-5'>程</b>最全面詳解

    Python后端項目的是什么

    最近公司 Python 后端項目進行重構,整個后端邏輯基本都變更為采用“異步”的方式實現。看著滿屏幕經過 async await(在 Python 中的實現)修飾的代碼,我頓時
    的頭像 發表于 09-23 14:38 ?1308次閱讀

    Python與JavaScript的對比及經驗技巧

    前言以前沒怎么接觸前端,對 JavaScript 的異步操作不了解,現在有了點了解。一查發現 Python 和 JavaScript 的發展史簡直就是一毛一樣!這里大致做下橫向對比和總結,便于
    的頭像 發表于 10-20 14:30 ?1890次閱讀

    使用channel控制數量

    goroutine 是輕量級線程,調度由 Go 運行時進行管理的。Go 語言的并發控制主要使用關鍵字 go 開啟 goroutine。Go (Goroutine)之間通過信道(
    的頭像 發表于 09-19 15:06 ?1117次閱讀

    詳解Linux線程、線程與異步編程、與異步

    不是系統級線程,很多時候被稱為“輕量級線程”、“微線程”、“纖(fiber)”等。簡單來說可以認為
    的頭像 發表于 03-16 15:49 ?950次閱讀

    的概念及的掛起函數介紹

    是一種輕量級的線程,它可以在單個線程中實現并發執行。與線程不同,不需要操作系統的上下文切換,因此可以更高效地使用系統資源。Kotlin
    的頭像 發表于 04-19 10:20 ?871次閱讀

    Kotlin實戰進階1

    的概念在1958年就開始出現(比線程還早), 目前很多語言開始原生支, Java 沒有原生但是大型公司都自己或者使用第三方庫來支持
    的頭像 發表于 05-30 16:24 ?682次閱讀
    <b class='flag-5'>Kotlin</b><b class='flag-5'>協</b><b class='flag-5'>程</b><b class='flag-5'>實戰</b><b class='flag-5'>進階</b><b class='flag-5'>之</b><b class='flag-5'>筑</b><b class='flag-5'>基</b><b class='flag-5'>篇</b>1

    Kotlin實戰進階3

    的概念在1958年就開始出現(比線程還早), 目前很多語言開始原生支, Java 沒有原生但是大型公司都自己或者使用第三方庫來支持
    的頭像 發表于 05-30 16:26 ?672次閱讀

    FreeRTOS任務與介紹

    是為那些資源很少的 MCU 準備的,其開銷很小,但是 FreeRTOS 官方已經不打算再更新了。 任務特性: 1、簡單。 2、沒
    的頭像 發表于 09-28 11:02 ?951次閱讀

    C++20無棧超輕量高性能異步庫開發實戰

    來了,c++標準委員會的謹慎態度也造就了c++20的給出來:“性能優秀”,“開發靈活”和讓人勸退的“門檻之高”。 不過話說回來,c++從出身就注定了背負性能使命,他不是為簡單為
    的頭像 發表于 11-09 10:20 ?1192次閱讀

    的實現與原理

    前言 這個概念很久了,好多程序員是實現過這個組件的,網上關于的文章,博客,論壇都是汗牛充棟,在知乎,github上面也有很多大牛寫了關于
    的頭像 發表于 11-10 10:57 ?415次閱讀

    Linux線程、線程與異步編程、與異步介紹

    不是系統級線程,很多時候被稱為“輕量級線程”、“微線程”、“纖(fiber)”等。簡單來說可以認為
    的頭像 發表于 11-11 11:35 ?1053次閱讀
    Linux線程、線程與異步編程、<b class='flag-5'>協</b><b class='flag-5'>程</b>與異步介紹