使用Java 9 Flow進行響應式程式設計
在本指南中,您將學習Java 9中的Flow API如何幫助您使用新的Publisher和Subscriber構建反應模式。閱讀之後,您應該能夠理解這種新的程式設計風格及其優缺點。
本指南重點介紹新的 Flow API,它使我們能夠僅使用JDK採用Reactive Programming,而不需要其他庫,如RxJava或Project Reactor等。
但是,在看了API之後,你很快就會發現這個API由幾個介面和一個實現組成:
- 介面 Flow.Publisher <T>定義了生成專案和控制訊號的方法。
- Flow.Subscriber <T> 介面 定義了接收這些訊息和訊號的方法。
- Flow.Subscription介面 定義了連結釋出伺服器和訂閱伺服器的方法。
- 介面 Flow.Processor <T,R>定義了一些方法來執行一些高階操作,例如將專案的轉換從釋出者連結到訂閱者。
- 最後,SubmissionPublisher類 <T>實現了Flow.Publisher <T>,它是一個靈活的專案生成器,符合Reactive Streams計劃。
即使沒有很多類可以使用,包括Java 9中的這個API也是一個重大變化:第三方可以為依賴於這些介面的庫提供Reactive支援,例如從JDBC驅動程式到RabbitMQ的反應式實現。
從Pull 到Push 再到Pull-Push
反應式程式設計主要是消費者控制資料流,由於它整合在主要框架和庫分發版(例如Java 9或Spring 5)中,它現在變得流行,並且分散式系統的興起帶來了大量的資料需要相互關聯傳達。
回顧過去有助於我們瞭解其崛起。幾年前,從消費者那裡獲取資料的最流行的技術是基於Pull 拉的機制。客戶端定期輪詢資料,如果可用,他們會讀取資料。優點是,在資源較少的情況下,他們可以控制資料流(停止輪詢); 主要缺點是在沒有任何消耗時透過輪詢資料浪費處理時間和/或網路資源。
隨著時間的推移,趨勢發生了變化,從生產者那裡推送資料並讓消費者照顧它變得很受歡迎。問題在於消費者可能擁有比生產者更有限的資源,在消費者緩慢和資料丟失的情況下最終會得到完整的輸入緩衝。如果只發生在我們訂閱者中的一小部分使用者,這可能會很好,但是如果它發生在大多數使用者身上呢?我們可以做得更好,減緩我們的生產者釋出...
Reactive Programming附帶的混合推拉Pull-Push方法試圖帶來兩全其美:它讓消費者負責請求資料並控制來自發布者的流量,這也可以在阻止或丟棄資料時做出決定資源。我們將在下面看到一個很好的實際例子。
Flow和Stream的區別
應式程式設計並不是取代函式程式設計。兩者相容並且完美地協同工作。雖然Java 8中引入的Streams API非常適合處理資料流(map,reduce和所有變體),但Flow API會在通訊方面(請求,減速,丟棄,阻塞等)發揮作用。
您可以將Streams用作Publisher的資料來源,根據需要阻止它們或刪除專案。您也可以在訂閱者身邊使用它們,例如,在收到某些專案後執行聚合。更不用說所有其他的程式設計邏輯,其中反應流不適合,但它可以用函式式編寫,並且比指令式程式設計的可讀性和維護更容易十倍。
有個困擾:如果你需要兩個系統之間交換並轉換資料怎麼辦?Stream和Flow如何一起工作?在這種情況下,我們可以使用Java 8函式將源對映到目標(轉換它)但我們不能在釋出者和訂閱者之間使用Stream,對嗎?
我們可能會想到在兩者之間建立一個訂閱者,它從原始釋出者那裡獲取專案,轉換它,然後像釋出者那樣釋出。好訊息:這就是Java 9的Flow.Processor<T, R>模式, 所以我們只需要實現該介面並在那裡編寫函式來轉換資料。
就個人而言,我不喜歡全反應, 過度反應或成為反應性佈道者(我無法決定具體的術語)。儘量不要為此瘋狂。
案例
本指南中包含的示例程式碼模擬了Magazine Publisher用例。釋出者只有兩個訂閱者。
出版商將為每位訂閱者製作一系列20種雜誌。他們知道他們的讀者在交貨時通常不在家,他們想避免郵遞員退回雜誌或扔掉雜誌。這可能發生,因為釋出者知道訂閱者的郵箱通常很小,無法放置更多郵件(訂閱者的緩衝區)。
取而代之的是,他們實施了一個非常創新的交付系統:使用者在他們在家時打電話給他們,他們幾乎立即交付一本雜誌。出版商計劃在辦公室為每位訂閱者保留一個小盒子,以防有些人在釋出雜誌後不立即致電該雜誌。經理認為在發行人辦公室為每個訂戶保留最多8個雜誌的空間已經足夠了(注意緩衝區現在是如何在出版商那邊)。
然後,其中一名工人前往經理辦公室,警告他們不同的情況:
- 如果訂閱者的速度足以要求傳送,就像釋出者正在列印新雜誌一樣快,就不會有空間問題。
- 如果訂閱者沒有像列印雜誌那樣以相同的速度打電話,那麼這些盒子可能會變滿。工人要求管理者應如何 作出反應,以這種情況下:
- 將每個使用者的盒子大小增加到20,這將解決問題(即釋出者方面的更多資源)。
- 停止列印直到情況得到修復(訂閱者請求至少一個)然後放慢速度,這會損害一些可能足夠快以使他們的盒子保持空白的訂閱者。
- 在生產後立即將任何不適合訂戶盒的雜誌扔到回收站(丟棄)。
- 中間解決方案:如果任何一個框已滿,請在列印下一個數字之前等待最長時間。如果在那之後還沒有空間,那麼他們將回收(丟棄)新號碼。
經理解釋說,他們買不起第一個解決方案,花費這麼多資源只是為了應對緩慢的使用者將是一種浪費,並決定選擇禮貌等待(d),這可能會損害一些使用者,但只是為了減少時間。營銷團隊決定將這種方法稱為Reactive Magazine Publishing,因為它“適應了他們的讀者”。提升上述分析的工人成為本月的員工。
(暈倒,這個案例用例夠複雜的,業務複雜,技術複雜,不適合學習!需要詳細瞭解可點選標題看原文)
在GitHub上找到原始碼:Java 9 Flow - Reactive
相關文章
- Kotlin Flow響應式程式設計,StateFlow和SharedFlowKotlin程式設計
- 使用Reactor響應式程式設計React程式設計
- Java9第四篇-Reactive Stream API響應式程式設計JavaReactAPI程式設計
- 快速使用 vscode 進行 Java 程式設計VSCodeJava程式設計
- 函式響應式程式設計與RxSwift函式程式設計Swift
- 響應式程式設計入門(RxJava)程式設計RxJava
- 響應式程式設計庫RxJava初探程式設計RxJava
- 揚帆起航:從指令式程式設計到函式響應式程式設計程式設計函式
- 響應式程式設計簡介之:Reactor程式設計React
- 響應式程式設計機制總結程式設計
- Java程式設計方法論-響應式 之 Rxjava篇 視訊解讀程式設計RxJava
- 完美解釋 Javascript 響應式程式設計原理JavaScript程式設計
- 對響應式程式設計的懷疑 - lukaseder程式設計
- RxJS 系列故事(1)——理解響應式程式設計JS程式設計
- Java多執行緒程式設計筆記9:ReentrantReadWriteLockJava執行緒程式設計筆記
- 使用 VS Code 進行 Python 程式設計Python程式設計
- 使用Cassandra進行.Net程式設計NY程式設計
- 響應式設計?響應式設計的基本原理是什麼?如何做?
- 響應式程式設計與MVVM架構—理論篇程式設計MVVM架構
- Spring 5與Spring cloud的響應式程式設計之旅SpringCloud程式設計
- 前端RxJs響應式程式設計之運算子實踐前端JS程式設計
- 使用Visual Studio Code進行MicroPython程式設計Python程式設計
- 淺談前端響應式設計(一)前端
- 淺談前端響應式設計(二)前端
- [java設計模式]單例設計模式,程式也要進行計劃生育。Java設計模式單例
- Spring Boot 中的響應式程式設計和 WebFlux 入門Spring Boot程式設計WebUX
- 響應式程式設計在Android 中的一些探索程式設計Android
- RxDart——Dart和Flutter中的響應式程式設計入門DartFlutter程式設計
- Spring響應式Reactive程式設計的10個陷阱 -Jeroen RosenbergSpringReact程式設計ROS
- 響應式程式設計基礎教程:Spring Boot 與 Lettuce 整合程式設計Spring Boot
- 使用反應式程式設計替換Java自動資源管理 - Arvind程式設計Java
- Responsive Web Design 響應式網頁設計Web網頁
- Tailwind CSS 響應式設計實戰指南AICSS
- [譯]Flutter 響應式程式設計:Steams 和 BLoC 實踐範例Flutter程式設計BloC
- 第七章:C#響應式程式設計System.ReactiveC#程式設計React
- 【python socket程式設計】—— 3.響應Python程式設計
- Java 網路程式設計 —— 非阻塞式程式設計Java程式設計
- 使用Java實現多執行緒程式設計Java執行緒程式設計