iT邦幫忙

2021 iThome 鐵人賽

DAY 10
0
Mobile Development

解鎖kotlin coroutine的各種姿勢-新手篇系列 第 10

聊聊structure concurrency 結構化併發

前面我們談了,coroutine的coroutineScope繼承異常處理取消,也在文中提到了他們和structure concurrency的特性,想必大家都已經有一點基本概念。

這篇文章,主要會先討論為甚麼coroutine要用structure concurrency,是要解決什麼問題,之後複習一下那些提過的特性,幫大家把我的文章前後連貫起來。

為什麼用structure concurrency

在討論為什麼用之前,不如先談談如果不用會怎樣?
假設今天我在需要發出100個請求,(官方blog是舉例1000啦,但我覺得二位數後都很麻煩),我就需要手動追蹤所有的coroutine,檢查Exception,更甚者當我們要取消剩餘任務時,也需要針對全數進行檢查狀態和取消。

如果今天,粗心了忘記取消某個coroutine任務,就會work Leak,那work leak是什麼?

他和memory leak的共通點就是都會占用內存,而work leak更糟糕,他有可能在背後更改到資料庫、發出網路請求,占用cpu資源等等,而coroutine的開發者針對這種問題,引入了Structure concurrency,以達到下列三點

  1. 不需要時自動取消任務
  2. 在運行時自動追蹤任務
  3. 當coroutine執行失敗時 throw Exception

而在kotlin coroutine裡面,分別以下列特性展現

  1. 當一個coroutineScope取消時,所有他之下的Job都會連帶取消
  2. suspend fun 確保他返回時,所有內部工作都已完成
  3. 當一個coroutine throw Exception,他的parent coroutine或caller會被通知

看著熟悉吧,就是前面我講過的那些,既然已經懂了為什麼要用structure concurrency,現在來複習一下吧

在kotlin裡,所有的coroutine都必須在coroutineScope裡面運行,而開啟一個coroutineScope的方式有下面幾種

  1. CoroutineScope -自己客制一個
  2. GlobalScope -跟著application生命週期的
  3. MainScope -supervisorJob() + Dispatcher.Main
  4. lifecycleScope -跟著fragment/activity lifecycleScope生命週期的
  5. viewModelScope -跟著viewModel lifecycleScope生命週期的
  6. runBlocking - 測試用的

cancel with structure concurrency

當我們創建了coroutineScope後,它會自動追蹤在該作用域的每個coroutine,可透過launch/async開啟coroutine,而coroutine的取消是透過 throw CancellationException來取消,取消的行為,只會影響自身跟子coroutine,對parent和sibiling不會有影響

這個特性,不只是Job.cancel()適用,Scope.cancel()也同樣套用這個規則,為了便於管理,我們經常會在一個scope裡面建立多個coroutine執行任務,那當我們不再需要那些任務執行時,只需要對scope呼叫cancel()即可,它會自動取消依附於他之下的coroutine

Structured concurrency guarantees when a scope cancels, all of its coroutines cancel.

Exception with structure concurrency

Structured concurrency guarantees that when a coroutine errors, its caller or scope is notified.

記得之前講過的Exception如何傳遞的吧,這邊就簡單複習一下,當一個coroutine throw Exception,他會通知她的parent,parent會再通知parent的parent,直到root,再全部取消

如果希望coroutine 出異常時,其他coroutine能繼續執行任務,應當使用supervisorJob或supervisorScope,並妥善處理Exception,具體資訊都寫在這裡

追蹤coroutine

另一個結構化病發的特點就是追蹤,在coroutineScope或supervisorScope裡面的coroutine,會被自動追蹤

範例是已發出1000個請求,其實不論launch/async,都只會在所有coroutine都完成工作後才會回傳,從而避免了work leak

連結
官方blog


上一篇
day9 Kotlin coroutine 的黑魔法 suspend
下一篇
day11 Kotlin coroutine 花生什麼事?
系列文
解鎖kotlin coroutine的各種姿勢-新手篇30

尚未有邦友留言

立即登入留言