多線程 Reactor 模式

目錄

多線程 Reactor 模式的核心動機

多線程演進方向

多線程 Reactor 模型結構

多線程 EchoServer 實現核心部分

Handler 的多線程化

多線程 Reactor 的三個核心點


本篇文章內容的前置知識為?單線程 Reactor 模式,如果不了解,可點擊鏈接學習
單線程 Reactor 模式-CSDN博客

多線程 Reactor 模式的核心動機

原因:單線程 Reactor 中,Reactor 線程和所有 Handler 處理器都共用同一個線程,一旦某個 Handler 執行時間較長,所有事件的處理都會被阻塞,系統無法橫向擴展。
目標:將 Reactor 和 Handler 的職責分離到多個線程中,提高并發能力,適應高連接數和重業務處理場景。

多線程演進方向

(1)升級 Handler:
將負責 IO 讀寫和業務邏輯的 Handler 放入獨立的線程池中異步處理,提高吞吐。
(2)升級 Reactor:
使用多個 Selector,創建多個子反應器(SubReactor),每個負責獨立的選擇操作。

多線程 Reactor 模型結構

客戶端請求
? ?↓
Reactor1(主反應器) ?→ ?accept handler(接收連接)
? ?↓ 分發給
Reactor2(子反應器) ?→ ?read/decode/compute/encode/write handler

Reactor 1 專職監聽新連接事件;
Reactor 2 專職監聽 IO 讀寫事件;
多個 Handler 在不同線程池中處理,互不阻塞。

多線程 EchoServer 實現核心部分

Reactor 主類

Selector[] selectors = new Selector[2];

一個 selector 專管連接接收(OP_ACCEPT);
一個 selector 專管數據讀寫(OP_READ/WRITE)。

SubReactor subReactor1 = new SubReactor(selectors[0]);
SubReactor subReactor2 = new SubReactor(selectors[1]);

為每個 selector 啟動一個線程,輪詢事件。

SubReactor 邏輯
子反應器的職責是:
負責輪詢 selector 中是否有事件發生;
若有事件觸發,就調用 dispatch() 方法,執行 handler。

SelectionKey sk = it.next();
Runnable handler = (Runnable) sk.attachment();
handler.run();

從 selectionKey 中拿出 attach 的 Handler;
直接執行 handler 的 run() 方法。

AcceptorHandler(連接處理器)

SocketChannel channel = serverSocket.accept();
new MultiThreadEchoHandler(selectors[1], channel);

接收連接后創建 IO Handler;
并將其注冊到數據讀寫 selector(selectors[1])中。

Handler 的多線程化

目標:將讀寫處理邏輯從 IO 事件輪詢線程中分離,提交到線程池異步處理。

核心實現:

static ExecutorService pool = Executors.newFixedThreadPool(4);
pool.submit(() -> asyncRun());

static ExecutorService pool = Executors.newFixedThreadPool(4);
創建一個包含 4 個線程的固定大小線程池,專門用于執行具體的業務邏輯(如數據處理、計算等)。線程池會復用這 4 個線程,避免頻繁創建銷毀線程的開銷。

pool.submit(() -> asyncRun());
將實際的業務處理邏輯(asyncRun() 方法,比如讀取數據、回顯數據的邏輯)提交到線程池執行。這樣做的核心目的是 讓 Reactor 線程(負責監聽和分發事件)不用等待業務處理完成,可以立即回去處理其他 IO 事件,避免被耗時操作阻塞。

asyncRun() 方法 的代碼思路和單線程 Reactor 模式的核心 run() 方法 代碼思路類似

單線程 Reactor 模式因 單線程瓶頸,僅適用于簡單場景;
Connection Per Thread 因 線程爆炸 問題,已被淘汰;
多線程 Reactor 模式通過 事件分離 + 線程池?解決了前兩者的缺陷

多線程 Reactor 的三個核心點

模塊處理職責所在線程
Main Reactor監聽連接(OP_ACCEPT)主線程
Sub Reactor監聽讀寫事件(OP_READ / OP_WRITE)線程1、線程2(子線程)
Handler(多線程)實際執行 IO + 業務邏輯提交給線程池異步執行

優勢對比

模型是否并發是否線程隔離是否支持線程池
單線程 Reactor
多線程 Reactor

Reactor 模式的優缺點

一、Reactor 模式與其他模式對比
(1)Reactor 模式 vs 生產者-消費者模式
相似之處:
二者都具有事件驅動特性。
在生產者-消費者模型中:
生產者產生任務(事件)并放入一個隊列。
消費者從隊列中拉取(pull)任務并處理。

Reactor 模式下:
客戶端連接、讀寫事件相當于生產者。
Selector 檢查事件是否就緒,相當于從“系統緩沖隊列”中拉取事件。
Handler 負責處理事件,相當于消費者。

不同之處:
生產者-消費者模型是基于「消息隊列」的顯式交互;
Reactor 模式是基于 IO 多路復用的「查詢式機制」(如 select、epoll)
Reactor 沒有明確的隊列,而是通過系統底層緩存區查詢到事件,再立即由 Dispatcher 分發給對應 Handler 處理。

(2)Reactor 模式 vs 觀察者模式
相似之處:
兩者都體現了事件監聽 + 響應處理的思想。
Reactor 中,Selector 檢測到事件 → Dispatcher 分發給對應 Handler。
觀察者模式中,主題 Topic 發生變化 → 通知所有訂閱該主題的觀察者 Observer。
都涉及“注冊監聽 + 回調響應”的機制。

不同之處:
觀察者模式允許一個事件被多個觀察者處理(一對多)
而 Reactor 模式中,一個 IO 事件只能交給一個 Handler 實例處理(一對一)
即:事件和處理器的綁定是唯一的,Handler 和 SelectionKey 是一一對應的。

二、Reactor 模式的優點
高響應性:
單線程模式:通過 非阻塞 IO + 事件驅動,避免了傳統阻塞 IO 中 一個連接阻塞導致全系統卡住?的問題(僅當 Handler 無阻塞操作時有效)
多線程模式:進一步通過 Reactor 線程與業務線程分離,即使某個業務邏輯阻塞,也不會影響 Reactor 線程處理其他連接,響應性更優。

編程簡單:
單線程模式:天然無多線程共享數據問題,不需要鎖和同步,邏輯最簡潔。
多線程模式:通過 職責分離(Reactor 線程管 IO,業務線程管邏輯),減少了共享數據的場景,相比 一連接一線程?模式,鎖和同步的復雜度更低。

良好的可擴展性:
多線程模式:可通過增加 Reactor 線程數(利用多核 CPU)、擴大業務線程池(處理更多并發業務)顯著提升吞吐量,擴展性更強。

三、Reactor 模式的缺點
模型實現較復雜:
相較于簡單的阻塞 IO,Reactor 涉及 Selector 注冊、事件派發、狀態管理,門檻較高;
不易調試,錯誤不易定位。

強依賴系統支持:
依賴于操作系統提供的高效 IO 多路復用機制(如 Linux 的 epoll);
若底層不支持 IO 復用,性能優勢無法體現,甚至可能適得其反。

Handler 內部阻塞會影響整體反應能力:
如果某個 Handler 內部業務邏輯阻塞太久(比如讀取大文件、等待數據庫響應),會導致整個 Selector 線程卡住,從而影響其他 IO 事件的派發,形成偽非阻塞。

模式特點是否規避偽非阻塞?
多 Reactor + 同步 Handler多線程負責 Selector,Handler 仍由 Selector 線程執行不能規避
多 Reactor + 異步 Handler(線程池)Selector 線程只分發事件,Handler 放入線程池處理能完全規避

同步異步handler主要是看它的run方法里面有沒有包含耗時/阻塞操作,比如read() / write()

偽非阻塞?指的是表面上使用了非阻塞 IO(如 NIO 的 SocketChannel 配置為非阻塞模式)和 Reactor 事件驅動模型,但由于某個環節(通常是 Handler 處理邏輯)出現阻塞,導致整個 Reactor 線程被卡住,最終失去了非阻塞模式應有的并發處理能力。

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

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

相關文章

[NLP]多電源域設計的仿真驗證方法

多電源域設計的仿真驗證方法 1. 更復雜的 Testbench 例子(多電源域、復雜低功耗場景) 假設有兩個電源域 PD1 和 PD2,分別對應控制信號 pwr_sw_ctrl1、iso_ctrl1、ret_ctrl1 和 pwr_sw_ctrl2、iso_ctrl2、ret_ctrl2,且兩域之間有通信。 RTL 端口聲明(簡化版) module top…

Apache Ignite 中 WHERE 子句中的子查詢(Subqueries in WHERE Clause)的執行方式

這段內容是關于 Apache Ignite 中 WHERE 子句中的子查詢(Subqueries in WHERE Clause)的執行方式 的說明。理解這段內容對于編寫高效的 SQL 查詢、避免性能瓶頸非常重要。下面我將為你 逐句解釋并深入理解這段內容。🧾 原文翻譯 解釋 原文&a…

MySQL(153)如何使用全文索引?

MySQL的全文索引(Full-Text Index)是一種特殊的索引類型,專門用于加速文本數據的搜索。與普通的B樹索引不同,全文索引適用于大文本字段(如TEXT、VARCHAR等)的全文搜索。它通過構建一個倒排索引,…

微分方程入門之入門之入門,純筆記

當描述 相對變化量 比 絕對量 更容易時,微分方程就經常用到了。 比如,描述為什么種群數量增加or減少【相對】,比描述為什么它在某個時間點是某個特定值【絕對】更容易。 物理學中,運動經常用力來描述,力–>代表變化…

【C++】簡單學——vector類(模擬實現)

模擬實現的準備工作 看源碼,了解這個類的大概組成 1.先看成員變量 成員變量的組成是三個迭代器 問:這個iterator內嵌類型究竟是什么?即這個迭代器是什么 迭代器實際就是T* 問:這三個迭代器代表什么意思? 連蒙帶猜…

【WRF】根據自動安裝腳本安裝 WRF / WRF-CHEM等

目錄 GitHub 上 WRF 自動安裝腳本 ?? 腳本的作用 ??? 支持的系統 ?? 可安裝的 WRF 版本及其選項 ? 如何使用(以 WRF 4.6.1 為例) ? 依賴庫的安裝位置 完整安裝腳本分析 參考 GitHub 上 WRF 自動安裝腳本 GitHub 上的 WRF-Install-Script 項目的 Releases(發布版本…

M2IV:面向大型視覺-語言模型中高效且細粒度的多模態上下文學習

MIV: Towards Efficient and Fine-grained Multimodal In Context Learning in Large Vision-Language Models COLM 2025 why 新興的研究方向:上下文學習(ICL)的效果“向量化”,其核心思想是用transformer內部的向量來…

龍迅#LT8711UXD適用于Type-C/DP1.4 /EDP轉 HDMI2.0 功能,分辨率高達4K60HZ,可支持HDCP!

1. 描述LT8711UXD 是一款高性能雙通道 Type-C/DP1.4 轉 HDMI2.0 轉換器,旨在將 USB Type-C 源或 DP1.4 源連接到 HDMI2.0 接收器。該LT8711UXD集成了一個符合 DP1.4 標準的接收器和一個符合 HDMI2.0 標準的發射器。此外,還嵌入了兩個用于CC通信的CC控制器…

《計算機組成原理與匯編語言程序設計》實驗報告一 基本數字邏輯及漢字顯示

目 錄 一、實驗學時 二、實驗目的 三、實驗要求 四、實驗內容 五、實驗步驟 1、打開Logisim軟件,列出異或邏輯電路真值表,并使用與、或、非基本原件實現異或邏輯電路。 2、打開Logisim軟件,列出同或邏輯電路真值表,并使用…

聚焦牛牛道:綠色積分模式如何實現快速發展?

?綠色消費積分政策再次進入大眾視野,這種能為企業減輕庫存負擔、讓咨金周轉更靈活的促銷方式,很快就成了焦點。牛牛道作為積極踐行這一政策的平臺,憑借其獨樹一幟的商業模式和運營思路,在短時間內就取得了顯著發展。一、牛牛道平…

高頻 RFID 賦能工業教學設備教學應用

高頻 RFID 賦能工業教學設備教學應用應用背景傳統工業教學設備側重機械原理、電氣控制等基礎功能演示,缺乏對 RFID 等工業識別技術的具象教學載體。學生在理論學習中難以直觀理解 RFID 技術的工業適配邏輯,實訓中缺乏設備識別系統的部署、調試經驗&#…

Transformer:顛覆NLP的自注意力革命

Transformer:顛覆NLP的自注意力革命 Transformer是自然語言處理領域中極具影響力的深度學習模型架構,以下是對其的詳細介紹: 提出背景與應用:2017年,Vaswani等人在《Attention Is All You Need》論文中首次提出Transformer架構,它主要用于處理序列到序列的任務,如機器翻…

基于 KeepAlived + HAProxy 搭建 RabbitMQ 高可用負載均衡集群

基于 KeepAlived HAProxy 搭建 RabbitMQ 高可用負載均衡集群 基于 KeepAlived HAProxy 搭建 RabbitMQ 高可用負載均衡集群實戰指南 一、前言 在企業級應用中,消息隊列的高可用性是系統穩定性的重要保障。RabbitMQ 作為主流的消息中間件,雖然自身支持…

京東獲得JD商品詳情 API 返回值說明||京東API接入文檔

京東商品詳情API返回值核心字段說明一、商品基礎信息商品ID(skuId/productId)唯一標識符,用于定位具體商品或SKU(如不同顏色、尺寸的變體)。示例:"skuId": "123456789"商品標題&#x…

其他世界的自來水

西歐,北美,亞洲日韓等地區,他們的自來水可以直接飲用以英國為例:自來水的質量可能等同或者有可能超過純凈水,不需要消毒和過濾直接可以飲用。直接從水龍接的水和瓶裝純凈水沒有什么差別,甚至比瓶裝純凈水更…

IO密集型、CPU密集型、負載、負載均衡

0、引入 從宏觀上來講,計算機可以抽象為【輸入 > 計算 > 輸出】這三部分 輸入輸出自然就是io,而計算部分自然歸cpu管 不同的任務,對io和cpu的依賴程度不同,由此有了cpu密集型任務和io密集型任務 1、IO密集型 更依賴輸入…

從甲方的角度看MOM項目成敗的原因

關鍵詞:MOM、數字化轉型、成敗數字化轉型中流行這么一句話:SAP項目加班到晚上8點,MOM項目最少到晚上10點。由此可見,MOM項目實施的難度、復雜度。但,為什么MOM難度大?先引入1個故事:1個價值300萬…

MySQL操作進階

系列文章目錄 MySQL的基礎操作-CSDN博客 目錄 系列文章目錄 前言 一、數據庫的約束 1. 約束類型:not null 2. 約束類型:unique 3. 約束類型:default 4. 約束類型:primary key 5. 約束條件:foreign key 二、表…

表征工程 中怎么 調整參數或比例

表征工程 中怎么 調整參數或比例 在表征工程(Representation Engineering)中,調整參數或比例的核心目標是平衡干預效果與模型基礎能力,避免過度干預導致語義失真或能力退化。以下是幾種常用的方法論及具體案例: 1. 系數縮放法(Scaling Coefficients):通過權重參數控制…

如何使用Anaconda(miniconda)和Pycharm

文章目錄前言具體操作Pycharm連接配置 Anaconda(miniconda)創建的虛擬環境PipAnacondaPyCharm三者關系一圖勝千言總結前言 本文介紹如何利用Anaconda和Pycharm這兩個強大的工具,實現Python項目的高效開發。通過構建虛擬環境、安裝依賴包及利…