1、Kotlin 協(xié)程(線程)切換
在協(xié)程中使用 launch善茎、async眼耀、Channel 和 Flow
4尿贫、withContext净蚤、runBlocking骨坑、launch锥咸、async 操作符
withContext 允許你在后臺(tái)線程執(zhí)行一些工作狭瞎,然后切換到主線程執(zhí)行UI操作,并最終返回操作的結(jié)果搏予。
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
fun main() = runBlocking {
launch(Dispatchers.Default) {
// 在后臺(tái)線程執(zhí)行一些工作
val result = withContext(Dispatchers.Main) {
// 切回主線程執(zhí)行UI操作
// 返回操作的結(jié)果 "Operation Result"
}
println("Result: $result")
}
}
join()熊锭、await()非阻塞式等待,直到線程結(jié)束雪侥,而不會(huì)將當(dāng)前線程掛起碗殷。
runBlocking:會(huì)阻塞當(dāng)前線程,直到所有在 runBlocking 內(nèi)部啟動(dòng)的協(xié)程都完成速缨。注意锌妻,它不會(huì)執(zhí)行上下文切換,而是在當(dāng)前線程上運(yùn)行協(xié)程旬牲。
launch 仿粹、async啟動(dòng)時(shí),必須要有協(xié)程范圍原茅,而runBlocking卻不需要吭历,其實(shí)runBlocking 也提供了一個(gè)協(xié)程作用域,但是它的使用方式和其他兩個(gè)不同擂橘,因?yàn)樗苯幼枞水?dāng)前線程晌区。
launch:用于在指定的上下文中啟動(dòng)協(xié)程,它會(huì)返回一個(gè) Job 對(duì)象贝室,允許你管理協(xié)程的生命周期契讲。通常與 async 或 withContext 結(jié)合使用。
async: 用于執(zhí)行異步操作滑频,它返回一個(gè) Deferred 對(duì)象捡偏,其實(shí)也是一個(gè)job,可以用于獲取操作的結(jié)果。與 await 結(jié)合使用以等待結(jié)果峡迷∫埃可以在不同的上下文中使用它你虹,以便執(zhí)行異步操作后切換回主線程。多個(gè)async依次執(zhí)行彤避,用await()等待傅物。
await:用于等待 Deferred 對(duì)象的結(jié)果。通常與 async 一起使用琉预。
withContext 與launch 區(qū)別:
launch :?jiǎn)?dòng)一個(gè)新的協(xié)程董饰,并立即返回 Job 對(duì)象,它并不會(huì)等待協(xié)程體完成圆米。
withContext :掛起當(dāng)前協(xié)程卒暂,并在指定上下文中執(zhí)行代碼塊,等待代碼塊執(zhí)行完成后繼續(xù)執(zhí)行娄帖。
supervisorScope:用于創(chuàng)建一個(gè)協(xié)程作用域也祠,其中的協(xié)程是獨(dú)立的,不會(huì)因?yàn)橐粋€(gè)子協(xié)程的失敗而取消其他子協(xié)程近速。這在處理并發(fā)任務(wù)時(shí)很有用诈嘿。
coroutineScope:用于創(chuàng)建一個(gè)協(xié)程作用域,其中的所有子協(xié)程必須執(zhí)行完成后削葱,它才會(huì)執(zhí)行完成奖亚。它也適用于并發(fā)任務(wù),但要求所有子協(xié)程都成功執(zhí)行佩耳。
2遂蛀、Channel和Flow都是Kotlin協(xié)程庫(kù)中的重要組件,用于處理數(shù)據(jù)流干厚,但它們有不同的用途和特性李滴。
Channel與Flow的共同點(diǎn)
異步通信:Channel和Flow都支持異步通信,允許協(xié)程之間以非阻塞的方式傳遞數(shù)據(jù)蛮瞄。
線程安全:它們?cè)趦?nèi)部都實(shí)現(xiàn)了線程安全的數(shù)據(jù)訪問機(jī)制所坯,確保數(shù)據(jù)在多個(gè)協(xié)程之間傳遞時(shí)的正確性。
協(xié)程支持:它們都是Kotlin協(xié)程庫(kù)的一部分挂捅,充分利用了協(xié)程的強(qiáng)大功能來簡(jiǎn)化異步編程芹助。
Channel與Flow的區(qū)別
Channel: 類似于熱流(Hot Stream),即使沒有收集器闲先,也會(huì)持續(xù)發(fā)送數(shù)據(jù)状土。
Flow: 類似于冷流(Cold Stream),只有在有收集器訂閱時(shí)才會(huì)開始發(fā)射數(shù)據(jù)伺糠。
使用場(chǎng)景:
Channel是一個(gè)雙向通道蒙谓,允許同時(shí)有多個(gè)生產(chǎn)者和消費(fèi)者。你可以通過send方法發(fā)送數(shù)據(jù)训桶,通過receive方法接收數(shù)據(jù)累驮。適用于復(fù)雜的并發(fā)場(chǎng)景酣倾,特別是在需要雙向通信或多生產(chǎn)者多消費(fèi)者的情況下。
Flow 更適合于簡(jiǎn)單的單向數(shù)據(jù)流傳遞谤专,你可以通過emit方法發(fā)送數(shù)據(jù)躁锡,通過collect方法接收數(shù)據(jù)。特別是當(dāng)只需要從一個(gè)源頭獲取數(shù)據(jù)時(shí)置侍。主要用于單向的數(shù)據(jù)流傳遞映之,通常只有一個(gè)生產(chǎn)者,可以有多個(gè)收集器(消費(fèi)者)墅垮。Flow更類似于RxJava的Observable或LiveData惕医。
數(shù)據(jù)消費(fèi):
Channel中的數(shù)據(jù)可以被多個(gè)消費(fèi)者消費(fèi),但每個(gè)數(shù)據(jù)項(xiàng)只能被消費(fèi)一次算色;互斥的。
而Flow數(shù)據(jù)流可以被多個(gè)收集器收集螟够,每個(gè)收集器會(huì)獨(dú)立地接收到相同的數(shù)據(jù)流副本灾梦。
主要用于單向的數(shù)據(jù)流傳遞。
冷流 vs 熱流:
Cold Flow: 只有在有收集器訂閱時(shí)才會(huì)開始發(fā)射數(shù)據(jù)妓笙。每次收集都會(huì)重新啟動(dòng)數(shù)據(jù)流的生成過程若河。
Hot Flow: 即使沒有收集器訂閱,也會(huì)持續(xù)發(fā)送數(shù)據(jù)寞宫。共享同一個(gè)數(shù)據(jù)源萧福,所有收集器會(huì)接收到相同的數(shù)據(jù)。
3辈赋、StateFlow和 SharedFlow是熱流鲫忍,在垃圾回收之前,都是存在內(nèi)存之中,并且處于活躍狀態(tài)的钥屈。
StateFlow是一個(gè)狀態(tài)容器式可觀察數(shù)據(jù)流可以向其收集器發(fā)出當(dāng)前狀態(tài)更新和新狀態(tài)更新悟民。還可通過其value屬性讀取當(dāng)前狀態(tài)值。
和livedata及其相似篷就。
SharedFlow會(huì)向從其中收集值的所有使用方發(fā)出數(shù)據(jù)射亏。有點(diǎn)類似BroadcastChannel,接收端都是可以收到消息的竭业。