Kotlin 協程 (三)

協程通信是協程之間進行數據交換和同步的關鍵機制。Kotlin 協程提供了多種通信方式,使得協程能夠高效、安全地進行交互。以下是對協程通信的詳細講解,包括常見的通信原語、使用場景和示例代碼。

1.1 Channel

定義:Channel 是一個消息隊列,用于協程之間的通信。它允許協程發送和接收數據,類似于 MPI(Message Passing Interface)中的消息傳遞機制。

特點:

  • 線程安全。
  • 支持多種通信模式,如無緩沖、有緩沖和無限緩沖。
  • 提供掛起函數?send?和?receive,用于發送和接收數據。
  • 可以關閉。

Channel 類型

類型描述創建方式適用場景
Rendezvous無緩沖(默認)Channel<T>()嚴格的發送-接收同步
Buffered固定大小緩沖Channel<T>(capacity)控制內存使用
Conflated保留最新值Channel<T>(CONFLATED)只需要最新數據
Unlimited無限緩沖Channel<T>(UNLIMITED)生產者快于消費者
Broadcast廣播給多個接收者BroadcastChannel<T>(capacity)一對多通信

使用場景:

1.生產者-消費者模式
  • 場景描述:一個或多個生產者協程生成數據,一個或多個消費者協程處理數據。
  • 適用性:當數據需要按順序處理時,Channel?提供了天然的 FIFO 隊列。
  • 示例:文件處理流水線,其中文件讀取、處理和寫入由不同的協程完成。
2 .協程間的事件總線
  • 場景描述:一個協程發送事件,多個協程監聽并響應這些事件。
  • 適用性:當需要解耦協程之間的通信時,Channel?可以作為事件傳遞的媒介。
  • 示例:在 GUI 應用中,用戶操作(如按鈕點擊)通過?Channel?發送事件,不同的協程根據事件執行相應的邏輯。
3. 資源池管理
  • 場景描述:多個協程需要共享一組有限資源,如數據庫連接或網絡請求。
  • 適用性:Channel?可以控制對資源的并發訪問,避免資源爭用導致的沖突。
  • 示例:使用?Channel?作為資源池,協程從池中請求資源,使用完畢后釋放回池中

示例:

fun main() = runBlocking {val channel = Channel<Int>() // 創建無緩沖通道// 生產者協程launch {for (x in 1..5) {println("Sending $x")channel.send(x) // 掛起直到有接收者delay(100) // 模擬工作}channel.close() // 關閉通道}// 消費者協程launch {for (y in channel) { // 使用for循環接收println("Received $y")}println("Channel is closed")}delay(2000)
}
1.2 Flow

定義:Flow?是一種冷流(cold stream),意味著數據流只有在收到收集(collection)請求時才會開始發射數據。它支持掛起操作,可以與協程完美結合,實現異步計算和數據處理。

特點:

  • 異步數據流:以異步方式處理連續數據流。
  • 聲明式編程:通過操作符鏈式調用處理數據流。
  • 可組合性:支持 map、filter、flatMap、zip 等操作符。
  • 取消支持:與協程一樣支持取消操作。

基本使用:

//使用 flow 建造器創建一個 Flow 對象。
fun transformFlow() = flow {for (i in 1..5) {delay(100)emit(i)}
}.map { it * 2 } // 將每個值乘以 2.filter { it > 4 } // 過濾掉小于等于 4 的值fun main() = runBlocking {
//使用 collect 函數收集 Flow 發射的數據。transformFlow().collect { value -> println("Transformed value: $value")}
}

使用場景:

1 .異步數據流處理
  • 場景描述:對異步數據流進行轉換、合并、過濾等操作。
  • 適用性:當需要對數據流進行復雜的操作時,Flow?提供了豐富的操作符。
  • 示例:在數據處理管道中,使用?Flow?對數據進行映射、過濾和歸約。
2. 網絡請求與數據解析
  • 場景描述:從網絡獲取數據,并進行解析和轉換。
  • 適用性:Flow?可以與網絡庫(如 Retrofit)結合,簡化異步網絡請求的處理。
  • 示例:使用?Flow?處理分頁網絡請求,逐頁獲取數據并進行解析。
3.?數據庫查詢與觀察
  • 場景描述:從數據庫查詢數據,并對結果進行觀察。
  • 適用性:Flow?可以與數據庫庫(如 Room)結合,實現數據的異步查詢和實時更新。
  • 示例:在 Android 應用中,使用?Flow?監聽數據庫表的變化,并更新 UI。

示例:

import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import kotlinx.coroutines.*interface ApiService {@GET("data")fun fetchData(): Flow<String>
}val apiService = Retrofit.Builder().baseUrl("https://api.example.com").addConverterFactory(GsonConverterFactory.create()).build().create(ApiService::class.java)fun main() = runBlocking {apiService.fetchData().flowOn(Dispatchers.IO) // 在 IO 線程上執行網絡請求.collect { data ->println("Received data: $data")}
}
1.3 SharedFlow 和 StateFlow

定義:SharedFlow 和 StateFlow 是 Kotlin Flow 庫中的兩種特殊 Flow,用于在多個收集器之間共享狀態和數據流。

特點:

  • SharedFlow:熱流,允許多個收集器接收數據,可配置重放(replay)和緩沖,不保存狀態。
  • StateFlow:特殊的 SharedFlow,必須有初始值,只保留最新值,并在收集器加入時立即發出當前狀態。

使用場景:

1.?事件流共享
  • 場景描述:多個協程需要共享同一個事件流,并且每個協程都能接收到事件。
  • 適用性:當事件需要被多個訂閱者處理,且每個訂閱者都能獨立地接收事件時。
  • 示例:在實時數據應用中,傳感器數據通過?SharedFlow?分發給多個處理單元。
2?狀態廣播
  • 場景描述:一個協程更新狀態,多個協程監聽狀態變化。
  • 適用性:當狀態變化需要通知給多個觀察者時,SharedFlow?提供了廣播機制。
  • 示例:在游戲開發中,玩家狀態(如生命值、分數)通過?SharedFlow?廣播給 UI 和邏輯處理單元。
3. 背壓管理
  • 場景描述:生產者生成數據的速度可能快于消費者處理數據的速度。
  • 適用性:SharedFlow?支持背壓策略,可以控制數據的發送速度,避免消費者過載。
  • 示例:在數據流處理中,使用?SharedFlow?緩解高速數據源對處理單元的壓力。

示例:

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*fun main() = runBlocking {val sharedFlow = MutableSharedFlow<String>()// 事件發送協程launch {sharedFlow.emit("Event 1")delay(1000)sharedFlow.emit("Event 2")}// 事件監聽協程 1launch {sharedFlow.collect { event ->println("Listener 1 received: $event")}}// 事件監聽協程 2launch {sharedFlow.collect { event ->println("Listener 2 received: $event")}}delay(2000) // 等待事件處理完成coroutineContext.cancelChildren() // 取消所有子協程
}
1.4?Await 和 Async

定義:async?是一種啟動協程并獲取其結果的方式。await?用于等待?async?協程的結果。

特點:

  • async?會立即返回一個?Deferred?對象,可以在需要時通過?await?獲取結果。
  • 支持結構化并發,await?會在需要時掛起協程,直到結果準備好。

使用場景:

  • 當需要并行執行任務并聚合結果時。
  • 當需要按需獲取協程結果時。

示例:

 import kotlinx.coroutines.*suspend fun main() {val deferred = async { expensiveComputation() }val result = deferred.await()println("Result: $result")}suspend fun expensiveComputation(): Int {delay(1000)return 42}
1.5 Actor

定義:Actor 是結合了協程和通道的實體,封裝了狀態和處理消息的能力。

特點:

  • 消息傳遞:Actor 之間通過發送和接收消息進行通信。
  • 封裝狀態:每個 Actor 封裝了自己的狀態和行為,其他 Actor 無法直接訪問其內部狀態。
  • 異步通信:通過消息傳遞實現異步交互,避免傳統并發模型中的死鎖和競爭問題。

使用場景:

  • 分布式系統:在分布式環境中,Actor 可以作為獨立的計算單元,通過消息傳遞完成協同任務。
  • 實時通信:適用于需要實時處理消息的場景,如聊天應用、游戲服務器等。
  • 高并發任務處理:處理需要同時執行多個任務的應用,例如訂單處理、數據分析等。

示例:

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*fun main() = runBlocking {val actor = actor<String> {//Actor 內部通過 for 循環接收來自 channel 的消息,并執行相應的處理邏輯。for (msg in channel) {println("Received: $msg")// 處理消息}}// 向 Actor 發送消息actor.send("Hello")actor.send("World")actor.close() // 關閉 Actor
}

2. 示例:實時搜索場景
class SearchViewModel : ViewModel() {// 使用 MutableStateFlow 存儲可變的搜索查詢字符串// StateFlow 是熱流,會自動收集數據,適合 UI 狀態管理private val searchQuery = MutableStateFlow("")// 使用 MutableStateFlow 存儲可變的搜索結果列表// 注意:這里返回的 searchResults 是不可變的 StateFlow,避免外部直接修改private val _searchResults = MutableStateFlow<List<String>>(emptyList())val searchResults: StateFlow<List<String>> = _searchResultsinit {// 在 viewModelScope 中啟動協程// viewModelScope 是 ViewModel 提供的協程作用域,基于 Dispatchers.Main 運行// 當 ViewModel 銷毀時,viewModelScope 會自動取消所有協程,避免內存泄漏viewModelScope.launch {// 構建 Flow 管道,處理搜索查詢到結果的轉換searchQuery// debounce(300):防抖處理,300ms 內多次輸入只觸發最后一次// 避免用戶快速輸入時觸發過多搜索請求.debounce(300)// filter it.length > 2:過濾短查詢,避免無效請求// 只有查詢長度大于 2 時才繼續處理.filter { it.length > 2 }// distinctUntilChanged():忽略重復的查詢,避免重復請求// 只有查詢內容變化時才繼續處理.distinctUntilChanged()// flatMapLatest:取消前一個未完成的搜索,只保留最新的查詢結果// 當新的查詢到來時,會取消前一個協程任務.flatMapLatest { query ->// 調用 performSearch 發起搜索,返回 Flow<List<String>>performSearch(query)}// catch emit(emptyList()):捕獲異常并返回空列表,避免 UI 出錯// 如果搜索過程中發生異常,會發射空列表作為默認結果.catch { emit(emptyList()) }// collect:收集 Flow 發射的數據,更新搜索結果.collect { results ->// 更新 _searchResults 的值,UI 會自動響應變化_searchResults.value = results}}}// 處理用戶輸入變化,更新搜索查詢fun onSearchQueryChanged(query: String) {// 直接設置 MutableStateFlow 的值,會觸發 Flow 管道重新計算searchQuery.value = query}// 模擬網絡搜索請求,返回 Flow<List<String>>private fun performSearch(query: String): Flow<List<String>> = flow {// delay(1000):模擬耗時操作(如網絡請求),可被協程取消// 如果協程被取消,delay 會立即拋出 CancellationExceptiondelay(1000)// emit:發射搜索結果// 這里模擬返回兩個結果項emit(listOf("query result 1", "query result 2"))}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/81877.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/81877.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/81877.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用SQLite Studio導出/導入SQL修復損壞的數據庫

使用SQLite Studio導出/導入SQL修復損壞的數據庫 使用Zotero時遇到了數據庫損壞&#xff0c;在軟件中寸步難行&#xff0c;遂嘗試修復數據庫。 一、SQLite Studio簡介 SQLite Studio是一款專為SQLite數據庫設計的免費開源工具&#xff0c;支持Windows/macOS/Linux。相較于其…

【git config --global alias | Git分支操作效率提升實踐指南】

git config --global alias | Git分支操作效率提升實踐指南 背景與痛點分析 在現代軟件開發團隊中&#xff0c;Git分支管理是日常工作的重要組成部分。特別是在規范的開發流程中&#xff0c;我們經常會遇到類似 feature/user-management、bugfix/login-issue 或 per/cny/dev …

(八)深度學習---計算機視覺基礎

分類問題回歸問題聚類問題各種復雜問題決策樹√線性回歸√K-means√神經網絡√邏輯回歸√嶺回歸密度聚類深度學習√集成學習√Lasso回歸譜聚類條件隨機場貝葉斯層次聚類隱馬爾可夫模型支持向量機高斯混合聚類LDA主題模型 一.圖像數字化表示及建模基礎 二.卷積神經網絡CNN基本原…

在tensorflow源碼環境里,編譯出獨立的jni.so,避免依賴libtensorflowlite.so,從而實現apk體積最小化

需要在APP里使用tensorflow lite來運行PC端訓練的model.tlite&#xff0c;又想apk的體積最小&#xff0c;嘗試了如下方法&#xff1a; 1. 在gradle里配置 implementation("org.tensorflow:tensorflow-lite:2.16.1") 這樣會引入tensorflow.jar&#xff0c;最終apk的…

neo4j框架:java安裝教程

安裝使用neo4j需要事先安裝好java&#xff0c;java版本的選擇是一個犯難的問題。本文總結了在安裝java和使用Java過程中遇到的問題以及相應的解決方法。 Java的安裝包可以在java官方網站Java Downloads | Oracle 中國進行下載 以java 8為例&#xff0c;選擇最后一行的x64 compr…

[服務器備份教程] Rclone實戰:自動備份數據到阿里云OSS/騰訊云COS等對象存儲

更多服務器知識&#xff0c;盡在hostol.com 各位服務器的守護者們&#xff0c;咱們都知道&#xff0c;數據是數字時代的“黃金”&#xff0c;而服務器上的數據更是我們業務的命脈。可天有不測風云&#xff0c;硬盤可能會突然“壽終正寢”&#xff0c;手滑執行了“毀滅性”命令…

Nextjs App Router 開發指南

Next.js是一個用于構建全棧web應用的React框架。App Router 是 nextjs 的基于文件系統的路由器&#xff0c;它使用了React的最新特性&#xff0c;比如 Server Components, Suspense, 和 Server Functions。 術語 樹(Tree): 一種用于可視化的層次結構。例如&#xff0c;包含父…

山東大學計算機圖形學期末復習15——CG15

CG15 OpenGL緩沖區、讀寫操作以及混合&#xff08;Blending&#xff09; 一、OpenGL緩沖區概述 OpenGL中的緩沖區是用于存儲像素數據的內存區域&#xff0c;主要包括以下類型&#xff1a; 顏色緩沖區&#xff08;Color Buffer&#xff09;&#xff1a;存儲每個像素的顏色值…

html+css+js趣味小游戲~記憶卡片配對(附源碼)

下面是一個簡單的記憶卡片配對游戲的完整代碼&#xff0c;使用HTML、CSS和JavaScript實現&#xff1a; html <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"wid…

?個并發訪問量?較?的key在某個時間過期,在redis中這個時間過期什么意思

在 Redis 中&#xff0c;當提到一個鍵&#xff08;key&#xff09;“在這個時間過期”&#xff0c;指的是為該鍵設置了生存時間&#xff08;TTL, Time To Live&#xff09;或過期時間&#xff08;expiration time&#xff09;。一旦到達設定的過期時間&#xff0c;Redis 會自動…

【設計模式】- 行為型模式1

模板方法模式 定義了一個操作中的算法骨架&#xff0c;將算法的一些步驟推遲到子類&#xff0c;使得子類可以不改變該算法結構的情況下重定義該算法的某些步驟 【主要角色】&#xff1a; 抽象類&#xff1a;給出一個算法的輪廓和骨架&#xff08;包括一個模板方法 和 若干基…

ubuntu22.04 卸載ESP-IDF

要在Ubuntu 22.04上完全卸載ESP-IDF&#xff0c;請按照以下步驟操作&#xff1a; 卸載ESP-IDF的步驟 刪除ESP-IDF目錄&#xff1a; # 假設ESP-IDF安裝在~/esp/esp-idf目錄 rm -rf ~/esp/esp-idf刪除ESP-IDF工具鏈和下載的工具&#xff1a; rm -rf ~/.espressif從PATH中移除ESP…

SQLMesh 內置宏詳解:@PIVOT等常用宏的核心用法與示例

本文系統解析 SQLMesh 的四個核心內置宏&#xff0c;涵蓋行列轉換的 PIVOT、精準去重的 DEDUPLICATE、靈活生成日期范圍的 DATE_SPINE&#xff0c;以及動態表路徑解析的 RESOLVE_TEMPLATE。通過真實案例演示參數配置與 SQL 渲染邏輯&#xff0c;并對比宏調用與傳統 SQL 的差異&…

基于Springboot + vue3實現的工商局商家管理系統

項目描述 本系統包含管理員、商家兩個角色。 管理員角色&#xff1a; 用戶管理&#xff1a;管理系統中所有用戶的信息&#xff0c;包括添加、刪除和修改用戶。 許可證申請管理&#xff1a;管理商家的許可證申請&#xff0c;包括搜索、修改或刪除許可證申請。 許可證審批管理…

第五部分:第五節 - Express 路由與中間件進階:廚房的分工與異常處理

隨著你的 Express 應用變得越來越大&#xff0c;所有的路由和中間件都寫在一個文件里會變得難以管理。這時候就需要將代碼進行拆分和組織。此外&#xff0c;一個健壯的后端應用必須能夠優雅地處理錯誤和一些常見的 Web 開發問題&#xff0c;比如跨域。 路由模塊化 (express.Ro…

萌新聯賽第(三)場

C題 這道題用暴力去寫想都不要想&#xff0c;一定超時&#xff0c;于是我們需要優化&#xff0c;下面是思路過程&#xff1a; 如圖&#xff0c;本題只需找到x的因數個數和(n-x)的因數個數&#xff0c;這兩個相乘&#xff0c;得到的就是對于這個x來說組合的個數&#xff0c;且x…

【Android構建系統】如何在Camera Hal的Android.bp中選擇性引用某個模塊

背景描述 本篇文章是一個Android.bp中選擇性引用某個模塊的實例。 如果是Android.mk編譯時期&#xff0c;在編譯階段通過某個條件判斷是不是引用某個模塊A, 是比較好實現的。Android15使用Android.bp構建后&#xff0c;要想在Android.bp中通過自定義的一個變量或者條件實現選…

【OneNET】_01_使用微信小程序通過新版OneNET平臺獲取STM32設備信息并進行控制

【OneNET】_01_使用微信小程序通過新版OneNET平臺獲取STM32設備信息并進行控制 一、 前言1.1 OntNET硬件方面: STM32F103C8T6 ESP01S教程 1.2 微信小程序方面 二、STM32代碼部分修改三、微信小程序修改的部分四、小筆記&#xff08;個人雜記&#xff09;4.1 OneNETOneNET物聯網…

用 python 編寫的一個圖片自動分類小程序(三)

圖片自動分類識別小程序記錄 2025/5/18 0:38修改程序界面&#xff0c;增加一些功能 用 python 編寫的一個圖片自動識別分類小程序。 操作系統平臺&#xff1a;Microsoft Windows 11 編程語言和 IDE&#xff1a;python 3.10 Visual studio code 一&#xff1a;圖片自動分…

嵌入式硬件篇---SGP30 氣體傳感器

文章目錄 前言一、SGP30 氣體傳感器詳解(一)基本概述(二)工作原理傳感器結構檢測機制自校準功能(三)主要特性(四)應用場景智能家居空氣質量檢測儀汽車行業商業建筑二、TVOC 與 eCO2 的含義(一)TVOC(總揮發性有機化合物)定義危害健康標準(二)eCO2(等效二氧化碳)…