Kotlin協(xié)程的理解

協(xié)程怎么理解

  • 一種在程序中處理并發(fā)任務的方案;也是該方案的一個組件
  • 協(xié)程和線程屬于一個層級的概念
  • 協(xié)程中不存在線程,也不存在并行(并行不是并發(fā))

協(xié)程的好處

  • 處理耗時任務,這種任務時常會堵塞主線程
  • 保證主線程安全,即確保安全地從主線程調用任何suspend函數(shù)
  • 協(xié)程讓異步邏輯同步化,杜絕回調地獄
  • 協(xié)程最核心的點就是,函數(shù)或者一段程序能夠掛起,稍后再在掛起的位置恢復

下面是關于協(xié)程這個概念的一些描述

協(xié)程的開發(fā)人員 Roman Elizarov 是這樣描述協(xié)程的:協(xié)程就像非常輕量級的線程。線程是由系統(tǒng)調度
的,線程切換或線程阻塞的開銷都比較大。而協(xié)程依賴于線程,但是協(xié)程掛起時不需要阻塞線程,幾乎是無
代價的,協(xié)程是由開發(fā)者控制的。所以協(xié)程也像用戶態(tài)的線程,非常輕量級,一個線程中可以創(chuàng)建任意個協(xié)
程。
Coroutine,翻譯成”協(xié)程“,初始碰到的人馬上就會跟進程和線程兩個概念聯(lián)系起來。直接先說區(qū)別,
Coroutine是編譯器級的,Process和Thread是操作系統(tǒng)級的。Coroutine的實現(xiàn),通常是對某個語言
做相應的提議,然后通過后成編譯器標準,然后編譯器廠商來實現(xiàn)該機制。Process和Thread看起來也在
語言層次,但是內生原理卻是操作系統(tǒng)先有這個東西,然后通過一定的API暴露給用戶使用,兩者在這里有
不同。Process和Thread是os通過調度算法,保存當前的上下文,然后從上次暫停的地方再次開始計算,
重新開始的地方不可預期,每次CPU計算的指令數(shù)量和代碼跑過的CPU時間是相關的,跑到os分配的cpu時
間到達后就會被os強制掛起。Coroutine是編譯器的魔術,通過插入相關的代碼使得代碼段能夠實現(xiàn)分段
式的執(zhí)行,重新開始的地方是yield關鍵字指定的,一次一定會跑到一個yield對應的地方
對于多線程應用,CPU通過切片的方式來切換線程間的執(zhí)行,線程切換時需要耗時(保存狀態(tài),下次繼
續(xù))。協(xié)程,則只使用一個線程,在一個線程中規(guī)定某個代碼塊執(zhí)行順序。協(xié)程能保留上一次調用時的狀
態(tài),不需要像線程一樣用回調函數(shù),所以性能上會有提升。缺點是本質是個單線程,不能利用到單個CPU的
多個核

扔物線表述

對某些語言,比如Kotlin,這樣說是沒有問題的,Kotlin的協(xié)程庫可以指定協(xié)程運行的線程池,我們只
需要操作協(xié)程,必要的線程切換操作交給庫,從這個角度來說,協(xié)程就是一個線程框架。

但理論上我們可以在單線程語言如JavaScript、Python上實現(xiàn)協(xié)程(事實上他們已經實現(xiàn)了協(xié)程),這時
我們再叫它線程框架可能就不合適了。

協(xié)程依賴

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0")

啟動

1.協(xié)程需要運行在有協(xié)程上下文環(huán)境,在非協(xié)程環(huán)境憑空啟動協(xié)程,有三種方式

  • GlobalScope.launch{}

在應用范圍內啟動一個協(xié)程,協(xié)程的生命周期與應用程序一致。這樣啟動的協(xié)程不能使線程?;睿拖袷刈o線程

由于這樣啟動的協(xié)程在啟動協(xié)程的組件已被銷毀但協(xié)程還存在的情況,可能導致資源耗盡,因此不推薦這樣啟動,尤其是在客戶端這種需要頻繁創(chuàng)建銷毀組件的場景

  • 實現(xiàn)CoroutineScope + launch{}

這是在應用場景最推薦使用協(xié)程的方式,為自己的組件實現(xiàn)CoroutieScope接口,在需要的地方使用launch{}方法啟動協(xié)程。使得協(xié)程和該組件生命周期綁定,組件銷毀時,協(xié)程一并銷毀。從而實現(xiàn)安全可靠的協(xié)程調用

  • runBlocking{}

啟動一個新協(xié)程,并阻塞當前線程,直到內部邏輯以及子線程邏輯全部執(zhí)行完成。
該方法的設計目的是讓suspend在編寫庫中能夠再常規(guī)堵塞代碼中使用,常在main方法和測試中使用

2.在一個協(xié)程中啟動子協(xié)程,一般來說有兩種

  • launch{}

異步啟動一個字寫成

  • async{}

異步啟動一個子協(xié)程,并返回Deffer對象,可通過調用Deffer.await()方法等待該子協(xié)程執(zhí)行完成并獲取結果,常用于并發(fā)-同步等待的情況

協(xié)程的掛起與恢復

  • 常規(guī)的函數(shù)基礎操作包括,invoke(或Call)和return,協(xié)程新增了suspend和resume
    1.suspend 也稱為掛起或者暫停,用于暫停執(zhí)行當前協(xié)程,并保存所有局部變量(掛起點保存了)

2.resume 用于讓已暫停的協(xié)程從其暫停處繼續(xù)執(zhí)行

  • 掛起函數(shù)
    1.使用suspend關鍵字修飾的函數(shù)叫做掛起函數(shù)

2.掛起函數(shù)只能在協(xié)程體內或者其他掛起函數(shù)內調用

調度器

  • 所有的協(xié)程都必須在調度器中運行,即使他們在主線程上也是如此
QQ20211214-161133@2x.png

如果協(xié)程沒有指定調度器的話,默認在dispatchers.Default運行

任務泄露

  • 當某個協(xié)程任務丟失,無法追蹤,導致內存、CPU、磁盤等資源浪費,甚至發(fā)送一個無用的網(wǎng)絡請求,這種情況叫做任務泄露
  • 為了能夠避免協(xié)程泄露,Kotlin引入了結構化并發(fā)機制

結構化并發(fā)

  • 取消任務,當某項任務不再需要時取消它
  • 追蹤任務,當任務正在執(zhí)行時,追蹤它
  • 發(fā)出錯誤信號,當協(xié)程失敗時,發(fā)出錯誤信號表明有錯誤發(fā)生
20211214-162408@2x.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容