異步程序設計方式

目錄

一、異步編程種類簡介

二、線程

三、回調

四、Future、 Promise 及其他

五、反應式擴展

六、協程


一、異步編程種類簡介

幾十年以來,作為開發人員,我們面臨著需要解決的問題——如何防止我們的應用程序被阻塞。 當我們正在開發桌面應用,移動應用,甚至服務器端應用程序時,我們希望避免讓用戶等待或導致更糟糕的原因成為阻礙應用程序擴展的瓶頸。

有很多途徑來解決這種問題,包括:

  • 線程
  • 回調
  • Future、 Promise 及其他
  • 反應式擴展
  • 協程

二、線程

到目前為止,線程可能是最常見的避免應用程序阻塞的方法。

fun postItem(item: Item) {val token = preparePost()val post = submitPost(token, item)processPost(post)
}fun preparePost(): Token {// 發起請求并因此阻塞了主線程return token
}

讓我們假設在上面的代碼中,preparePost?是一個長時間運行的進程,因此會阻塞用戶界面。我們可以做的是在一個單獨的線程中啟動它。這樣就可以允許我們避免阻塞 UI。這是一種非常常見的技術,但有一系列缺點:

  • 線程并非廉價的。線程需要昂貴的上下文切換。
  • 線程不是無限的。可被啟動的線程數受底層操作系統的限制。在服務器端應用程序中,這可能會導致嚴重的瓶頸。
  • 線程并不總是可用。在一些平臺中,比如 JavaScript 甚至不支持線程。
  • 線程不容易使用。調試線程與避免競爭條件是我們在多線程編程中遇到的常見問題。

三、回調

使用回調,其想法是將一個函數作為參數傳遞給另一個函數,并在處理完成后調用此函數。

fun postItem(item: Item) {preparePostAsync { token -> submitPostAsync(token, item) { post -> processPost(post)}}
}fun preparePostAsync(callback: (Token) -> Unit) {// 發起請求并立即返回// 設置稍后調用的回調
}

原則上這感覺就像一個更優雅的解決方案,但又有幾個問題:

  • 回調嵌套的難度。通常被用作回調的函數,經常最終需要自己的回調。這導致了一系列回調嵌套并導致出現難以理解的代碼。該模式通常被稱為標題圣誕樹(大括號代表樹的分支)。
  • 錯誤處理很復雜。嵌套模型使錯誤處理和傳播變得更加復雜。

回調在諸如 JavaScript 之類的事件循環體系結構中非常常見,但即使在那里,通常人們已經轉而使用其他方法,例如 promises 或反應式擴展。

四、Future、 Promise 及其他

futures 或 promises 背后的想法(這也可能會根據語言/平臺而有不同的術語),是當我們發起調用的時候,我們承諾在某些時候它將返回一個名為 Promise 的可被操作的對象。

fun postItem(item: Item) {preparePostAsync() .thenCompose { token -> submitPostAsync(token, item)}.thenAccept { post -> processPost(post)}}fun preparePostAsync(): Promise<Token> {// 發起請求并當稍后的請求完成時返回一個 promisereturn promise 
}

這種方法需要對我們的編程方式進行一系列更改,尤其是:

  • 不同的編程模型。與回調類似,編程模型從自上而下的命令式方法轉變為具有鏈式調用的組合模型。傳統的編程結構例如循環,異常處理,等等。通常在此模型中不再有效。
  • 不同的 API。通常這需要學習完整的新 API 諸如?thenCompose?或?thenAccept,這也可能因平臺而異。
  • 具體的返回值類型。返回類型遠離我們需要的實際數據,而是返回一個必須被內省的新類型“Promise”。
  • 異常處理會很復雜。錯誤的傳播和鏈接并不總是直截了當的。

五、反應式擴展

Erik Meijer) 將反應式擴展(Rx)引入了 C#. 雖然它在 .NET 平臺上是毫無疑義的, 但是在 Netflix 將它移植到 Java 并取名為 RxJava 之前絕對不是主流。從那時起,反應式被移植到各種平臺,包括 JavaScript(RxJS)。

Rx 背后的想法是走向所謂的“可觀察流”,我們現在將數據視為流(無限量的數據),并且可以觀察到這些流。 實際上,Rx 很簡單,?Observer Pattern?帶有一系列擴展,允許我們對數據進行操作。

在方法上它與 Futures 非常相似,但是人們可以將 Future 視為一個離散元素,而 Rx 返回一個流。然而,與前面類似,它還介紹了一種全新的思考我們的編程模型的方式,著名的表述是:

“一切都是流,并且它是可被觀察的”

這意味著處理問題的方式不同,并且在編寫同步代碼時從我們使用的方式發生了相當大的轉變。與 Futures 相反的一個好處是,它被移植到這么多平臺,通常我們可以找到一致的 API 體驗,無論我們使用 C#、Java、JavaScript,還是 Rx 可用的任何其他語言。

此外,Rx 確實引入了一種更好的錯誤處理方法。

六、協程

Kotlin 編寫異步代碼的方式是使用協程,這是一種計算可被掛起的想法。即一種函數可以在某個時刻暫停執行并稍后恢復的想法。

協程的一個好處是,當涉及到開發人員時,編寫非阻塞代碼與編寫阻塞代碼基本相同。編程模型本身并沒有真正改變。

以下面的代碼為例:

fun postItem(item: Item) {launch {val token = preparePost()val post = submitPost(token, item)processPost(post)}
}suspend fun preparePost(): Token {// 發起請求并掛起該協程return suspendCoroutine { /* ... */ } 
}

此代碼將啟動長時間運行的操作,而不會阻塞主線程。preparePost?就是所謂的?可掛起的函數,因此它含有?suspend?前綴。這意味著如上所述,該函數將被執行、暫停執行以及在某個時間點恢復。

  • 該函數的簽名保持完全相同。唯一的不同是它被添加了?suspend?修飾符。但是返回類型依然是我們想要的類型。
  • 編寫這段代碼代碼就好像我們正在編寫同步代碼,自上而下,不需要任何特殊語法,除了使用一個名為?launch?的函數,它實質上啟動了該協程(在其他教程中介紹)。
  • 編程模型和 API 保持不變。我們可以繼續使用循環,異常處理等,而且不需要學習一整套新的 API。
  • 它與平臺無關。無論我們是面向 JVM,JavaScript 還是其他任何平臺,我們編寫的代碼都是相同的。編譯器負責將其適應每個平臺。

協程并不是一個新的概念,它并不是 Kotlin 發明的。它們已經存在了幾十年,并且在 Go 等其他一些編程語言中很受歡迎。但重要的是要注意就是他們在 Kotlin 中實現的方式,大部分功能都委托給了庫。事實上,除了?suspend?關鍵字,沒有任何其他關鍵字被添加到語言中。這也是與其他語言的不同之處,例如 C# 將?async?以及?await?作為語法的一部分。而在 Kotlin 中,他們都只是庫函數。

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

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

相關文章

qt-Quick3D筆記之官方例程Runtimeloader Example運行筆記

qt-Quick3D筆記之官方例程Runtimeloader Example運行筆記 文章目錄 qt-Quick3D筆記之官方例程Runtimeloader Example運行筆記1.例程運行效果2.例程縮略圖3.項目文件列表4.main.qml5.main.cpp6.CMakeLists.txt 1.例程運行效果 運行該項目需要自己準備一個模型文件 2.例程縮略圖…

以太坊入門【詳解】

以太坊的組成部分 P2P網絡&#xff1a;以太坊在以太坊網絡上運行&#xff0c;該網絡可在TCP端口30303上尋址&#xff0c;并運行一個協議。交易&#xff1a;以太坊交易時網絡消息&#xff0c;其中包括發送者&#xff0c;接受者&#xff0c;值和數據的有效載荷以太坊虛擬機&…

實驗十四 EL和JSTL

實驗十四 EL和JSTL 一、實驗目的 1、掌握EL表達式的使用 2、掌握JSTL的使用 二、實驗過程 1、在數據庫Book中建立表Tbook&#xff0c;包含圖書ID&#xff0c;圖書名稱&#xff0c;圖書價格。實現在bookQuery.jsp頁面中模糊查詢圖書&#xff0c;如果圖書的價格在50元以上&#…

安裝和卸載RabbitMQ

我的飛書:https://rvg7rs2jk1g.feishu.cn/docx/SUWXdDb0UoCV86xP6b3c7qtMn6b 使用Ubuntu環境進行安裝 一、安裝Erlang 在安裝RabbitMQ之前,我們需要先安裝Erlang,RabbitMQ需要Erlang的語言支持 #安裝Erlang sudo apt-get install erlang 在安裝的過程中,會彈出一段信息,此…

音視頻多媒體編解碼器基礎-codec

如果要從事編解碼多媒體的工作&#xff0c;需要準備哪些更為基礎的內容&#xff0c;這里幫你總結完。 因為數據類型不同所以編解碼算法不同&#xff0c;分為圖像、視頻和音頻三大類&#xff1b;因為流程不同&#xff0c;可以分為編碼和解碼兩部分&#xff1b;因為編碼器實現不…

ML基礎-Jupyter notebook中的魔法命令

在 Jupyter Notebook 或 IPython 環境中&#xff0c;“魔法命令”&#xff08;Magic Commands&#xff09;是一些以百分號&#xff08;%&#xff09;或驚嘆號&#xff08;!)開頭的特殊命令&#xff0c;用于執行一些與代碼運行環境相關的操作&#xff0c;而不僅僅是執行普通的 P…

【Unity2D 2022:UI】創建滾動視圖

一、創建Scroll View游戲對象 在Canvas畫布下新建Scroll View游戲對象 二、為Content游戲對象添加Grid Layout Group&#xff08;網格布局組&#xff09;組件 選中Content游戲物體&#xff0c;點擊Add Competent添加組件&#xff0c;搜索Grid Layout Group組件 三、調整Grid La…

9-收納的知識

[ComponentOf(typeof(xxx))]組件描述&#xff0c;表示是哪個實體的組件 [EntitySystemOf(typeof(xxx))] 系統描述 [Event(SceneType.Demo)] 定義事件&#xff0c;在指定場景的指定事件發生后觸發 [ChildOf(typeof(ComputersComponent))] 標明是誰的子實體 [ResponseType(na…

數據庫系統概念第六版記錄 一

1.關系型數據庫 關系型數據庫&#xff08;Relational Database&#xff0c;簡稱 RDB&#xff09;是基于關系模型的一種數據庫&#xff0c;它通過表格的形式來組織和存儲數據。每個表由若干行&#xff08;記錄&#xff09;和列&#xff08;字段&#xff09;組成&#xff0c;數據…

Vue前端開發-pinia之Actions插件

Store中的Actions部分&#xff0c;用于定義操作屬性的方法&#xff0c;類似于組件中的methods部分&#xff0c;它與Getters都可以操作State屬性&#xff0c;但在定義方法時&#xff0c;Getters是對State屬性進行加工處理&#xff0c;再返回使用&#xff0c;屬于內部計算;Action…

生成式AI安全最佳實踐 - 抵御OWASP Top 10攻擊 (下)

今天小李哥將開啟全新的技術分享系列&#xff0c;為大家介紹生成式AI的安全解決方案設計方法和最佳實踐。近年來生成式 AI 安全市場正迅速發展。據IDC預測&#xff0c;到2025年全球 AI 安全解決方案市場規模將突破200億美元&#xff0c;年復合增長率超過30%&#xff0c;而Gartn…

一個開源 GenBI AI 本地代理(確保本地數據安全),使數據驅動型團隊能夠與其數據進行互動,生成文本到 SQL、圖表、電子表格、報告和 BI

一、GenBI AI 代理介紹&#xff08;文末提供下載&#xff09; github地址&#xff1a;https://github.com/Canner/WrenAI 本文信息圖片均來源于github作者主頁 在 Wren AI&#xff0c;我們的使命是通過生成式商業智能 &#xff08;GenBI&#xff09; 使組織能夠無縫訪問數據&…

JAVA架構師進階之路

JAVA架構師進階之路 前言 苦于網絡上充斥的各種java知識&#xff0c;多半是互相抄襲&#xff0c;導致很多后來者在學習java知識中味同嚼蠟&#xff0c;本人閑暇之余整理了進階成為java架構師所必須掌握的核心知識點&#xff0c;后續會不斷擴充。 廢話少說&#xff0c;直接上正…

java程序員面試自身優缺點,詳細說明

程序員面試大廠經常被問到的Java異常機制問題,你搞懂了嗎運行時異常:運行時異常是可能被程序員避免的異常。與檢查性相反,運行時異常可以在編譯時被忽略。錯誤(ERROR):錯誤不是異常,而是脫離程序員控制的問題。錯誤通常在代碼中容易被忽略。例如:當棧溢出時,一個錯誤就發生了,它…

C++六大默認成員函數

C六大默認成員函數 默認構造函數默認析構函數RAII技術RAII的核心思想優點示例應用場景 默認拷貝構造深拷貝和淺拷貝 默認拷貝賦值運算符移動構造函數&#xff08;C11起&#xff09;默認移動賦值運算符&#xff08;C11起&#xff09;取地址及const取地址操作符重載取地址操作符重…

Java 2024年面試總結(持續更新)

目錄 最近趁著金三銀四面了五六家公司吧&#xff0c;也整理了一些問題供大家參考一下&#xff08;適合經驗三年左右的&#xff09;。 面試問題&#xff08;答案是我自己總結的&#xff0c;不一定正確&#xff09;&#xff1a; 總結&#xff1a; 最近趁著金三銀四面了五六家公…

防火墻的安全策略

1.VLAN 2屬于辦公區;VLAN 3屬于生產區&#xff0c;創建時間段 [FW]ip address-set BG type object [FW-object-address-set-BG]address 192.168.1.0 mask 25 [FW]ip address-set SC type object [FW-object-address-set-SC]address 192.168.1.129 mask 25 [FW]ip address-se…

工作流項目BPMN.JS_Question梳理

工作流項目 想了解如果候選人熟悉工作流技術、bpmn.js和Flowable工作流引擎&#xff0c;面試官會對哪些信息感興趣。我需要分析這個問題&#xff0c;并給出一個全面而結構化的回答。 首先&#xff0c;用戶可能希望了解作為前端面試官&#xff0c;應該關注候選人哪些方面的知識和…

windows下搭建鴻蒙OS應用開發環境

一、前言 HUAWEI DevEco Studio 是華為推出的一款集成開發環境&#xff08;IDE&#xff09;&#xff0c;主要用于開發基于華為鴻蒙操作系統&#xff08;HarmonyOS&#xff09;的應用。作為華為開發者工具的核心之一&#xff0c;DevEco Studio 提供了一個多功能的開發平臺&…

MacBook Pro(M1芯片)Qt環境配置

MacBook Pro&#xff08;M1芯片&#xff09;Qt環境配置 1、準備 試圖寫一個跨平臺的桌面應用&#xff0c;此時想到了使用Qt&#xff0c;于是開始了搭建開發環境&#xff5e; 在M1芯片的電腦上安裝&#xff0c;使用brew工具比較方便 Apple Silicon&#xff08;ARM/M1&#xf…