Java學習----NIO模型

????????在 Java 的 I/O 模型中,NIO(Non - Blocking I/O,非阻塞 I/O)是對 BIO 的重要改進。它為高并發場景提供了更高效的處理方式,在眾多 Java 應用中發揮著關鍵作用。

????????NIO模型的核心在于非阻塞和多路復用,其采用 “一個線程處理多個連接” 的模式,主要依靠通道(Channel)、緩沖區(Buffer)和選擇器(Selector)這三個核心組件協同工作,每個核心組件的功能原理和功能如下:

(1)通道:通道是數據傳輸的通道,類似于 BIO 中的流,但它是雙向的,既可以從通道讀取數據,也可以向通道寫入數據。常見的通道有ServerSocketChannel(用于服務器端監聽連接)、SocketChannel(用于客戶端與服務器端的通信)等。?

(2)緩沖區:緩沖區是存儲數據的容器,所有數據的讀寫都必須通過緩沖區進行。它本質上是一個數組,提供了對數據的結構化訪問以及維護讀寫位置等信息。在 NIO 中,數據從通道讀取到緩沖區,或從緩沖區寫入到通道。?

(3)選擇器:選擇器是 NIO 實現多路復用的關鍵。它可以同時監控多個通道的事件(如連接請求、數據可讀、數據可寫等)。一個線程通過選擇器注冊多個通道,然后阻塞在選擇器上,等待通道事件的發生。當有事件發生時,線程會處理這些事件,從而實現一個線程高效處理多個連接。?

????????其工作流程大致為:服務器端通過ServerSocketChannel監聽端口,將其注冊到選擇器上,并設置關注的事件(如接受連接事件)。客戶端通過SocketChannel發起連接。選擇器不斷輪詢注冊的通道,當某個通道有事件發生時,就會被選中。線程從選擇器中獲取這些就緒的通道,進行相應的處理,如接受連接、讀取數據、寫入數據等,且這些操作大多是非阻塞的。?

? ? ? ? 作為BIO的改進型,NIO也是有著許多優點,例如:?

(1)高并發處理能力強:借助多路復用機制,一個線程可以處理多個連接,大大減少了線程的創建和銷毀帶來的開銷,以及線程上下文切換的成本,能在高并發場景下保持較好的性能。?

(2)非阻塞提升效率:在數據讀寫過程中,線程不會一直阻塞等待,當沒有數據可讀或可寫時,線程可以去處理其他通道的事件,提高了線程的利用率。?

(3)雙向傳輸更靈活:通道是雙向的,相比 BIO 中流的單向傳輸,在一些需要雙向數據交互的場景中,使用更方便靈活。?

? ? ? ? 但是同樣的,其缺點也不少,如:?

(1)編程復雜度高:NIO 的編程模型相對 BIO 更為復雜,需要理解通道、緩沖區、選擇器等多個組件的協同工作機制,對開發者的技術要求較高。?

(2)學習門檻較高:其涉及的多路復用、非阻塞等概念較難理解,新手需要花費更多的時間和精力去掌握。?

(3)在低并發場景下優勢不明顯:在并發量較小的情況下,NIO 的優勢難以體現,其復雜的機制可能還會帶來一些額外的開銷。?

????????下面通過一個簡單的客戶端 - 服務器通信示例來展示 Java NIO 的使用。?

服務器端代碼?

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;public class NioServer {public static void main(String[] args) throws IOException {// 創建ServerSocketChannel并綁定端口ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.socket().bind(new InetSocketAddress(8888));// 設置為非阻塞模式serverSocketChannel.configureBlocking(false);// 創建選擇器Selector selector = Selector.open();// 將ServerSocketChannel注冊到選擇器,關注接受連接事件serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服務器啟動,監聽端口8888...");while (true) {// 阻塞等待通道事件,返回就緒的通道數量int readyChannels = selector.select();if (readyChannels == 0) {continue;}// 獲取就緒的事件Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()) {SelectionKey key = iterator.next();// 移除處理過的事件,避免重復處理iterator.remove();if (key.isAcceptable()) {// 處理接受連接事件ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();SocketChannel socketChannel = serverChannel.accept();socketChannel.configureBlocking(false);// 將客戶端通道注冊到選擇器,關注數據可讀事件socketChannel.register(selector, SelectionKey.OP_READ);System.out.println("收到新的客戶端連接:" + socketChannel.getRemoteAddress());} else if (key.isReadable()) {// 處理數據可讀事件SocketChannel socketChannel = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);int bytesRead = socketChannel.read(buffer);if (bytesRead > 0) {buffer.flip();byte[] data = new byte[buffer.remaining()];buffer.get(data);String message = new String(data);System.out.println("收到客戶端消息:" + message);// 向客戶端發送響應buffer.clear();String response = "服務器已收到消息:" + message;buffer.put(response.getBytes());buffer.flip();socketChannel.write(buffer);} else if (bytesRead == -1) {// 客戶端關閉連接socketChannel.close();System.out.println("客戶端連接關閉");}}}}}
}
/*
創建ServerSocketChannel并綁定端口,設置為非阻塞模式,然后注冊到選擇器上并關注接受連接事件。進入循環后,線程阻塞在選擇器的select()方法上,等待通道事件。當有接受連接事件時,接受客戶端連接,將客戶端的SocketChannel注冊到選擇器并關注數據可讀事件。當有數據可讀事件時,從通道中讀取數據,處理后向客戶端發送響應。
*/

客戶端代碼?

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;public class NioClient {public static void main(String[] args) throws IOException {// 打開SocketChannel并連接服務器SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("localhost", 8888));// 設置為非阻塞模式socketChannel.configureBlocking(false);System.out.println("已連接到服務器");// 向服務器發送數據Scanner scanner = new Scanner(System.in);System.out.println("請輸入要發送的消息:");String message = scanner.nextLine();ByteBuffer buffer = ByteBuffer.allocate(1024);buffer.put(message.getBytes());buffer.flip();socketChannel.write(buffer);// 讀取服務器的響應buffer.clear();int bytesRead = socketChannel.read(buffer);if (bytesRead > 0) {buffer.flip();byte[] data = new byte[buffer.remaining()];buffer.get(data);String response = new String(data);System.out.println("收到服務器響應:" + response);}scanner.close();socketChannel.close();System.out.println("客戶端連接關閉");}
}
/*
創建SocketChannel連接服務器,設置為非阻塞模式,向服務器發送數據,然后讀取服務器的響應,最后關閉連接。
*/

????????從代碼中能清楚看到 NIO 的非阻塞和多路復用特性,一個線程通過選擇器處理多個通道的事件,極大地提高了并發處理能力。?

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

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

相關文章

MySQL計數函數count原理分析

前言 統計表中數據的條數是非常常用的操作,但是咱們常用的InnoDB存儲引擎計數函數是現時統計的,所以會出現性能的問題,這次我準備分享計數函數count的原理,保證之后遇到計數方面的問題都可以輕易靈活的解決 與MyISAM存儲引擎相比,MyISAM存儲引擎是自己記錄了表中數據的條數,但…

Day07_網絡編程20250721_大項目

基本代碼&#xff1a;搭建服務器客戶端&#xff0c;要求服務器使用 epoll 模型客戶端使用多線程服務器打開數據庫&#xff0c;表單格式如下name text primary key pswd text not null客戶端做一個簡單的界面&#xff1a;1&#xff1a;注冊2&#xff1a;登錄無論注冊還是登錄&am…

20250721

P5357 【模板】AC 自動機 - 洛谷 主要是構建fail樹 /* 我們可以知道的是&#xff0c;當訪問一個點x時&#xff0c;接下來需要跳轉其fail[x]&#xff0c;以此類推&#xff0c;如果在某個fail[x]上出現了一個字符串&#xff0c;那么相應的統計次數應該加1&#xff0c;然后當訪…

【INT四則優先算式】2022-9-22

緣由ccf201903-2二十四點我用暴力破解做的&#xff0c;但是兩個程序一個拿到了滿分&#xff0c;一個拿到了50分&#xff0c;看了很長時間也沒看出問題在哪里&#xff0c;希望有英雄慧眼幫我看一下-編程語言-CSDN問答 void INT四則優先算式() {//緣由https://ask.csdn.net/ques…

本地k8s集群的搭建

windows機器&#xff0c;考慮如果使用云服務器&#xff0c;每年的開銷還是太大&#xff0c;不值得&#xff0c;自己只是做demo&#xff0c;了解各種配置和使用即可&#xff0c;使用VMware的虛擬機來搭建k8s集群 使用docker安裝rancher和k8s yum -y install chronycat > /et…

B樹、B+樹的區別及MySQL為何選擇B+樹

B樹與B樹 B樹和B樹都是自平衡的多路搜索樹&#xff0c;廣泛應用于數據庫和文件系統中&#xff0c;用于高效管理大量數據。它們的設計目標是在磁盤存儲環境下減少I/O操作次數&#xff0c;提高數據訪問效率。下面我將逐步解釋兩者的定義、特性、比較以及應用場景&#xff0c;確保…

Unity之可視化編程VisualScripting快速入門

文章目錄 前言 腳本機和狀態機 腳本圖ScriptGraph 腳本圖 子圖 自定義事件 狀態圖StateGraph 狀態圖 Start狀態 創建新狀態 過渡連接 常用功能 射線檢測 補間動畫 按鈕點擊 前言 可視化腳本使您無需編寫代碼即可為游戲或應用程序創建邏輯。可視化腳本使用基于節點的可視化圖形…

2025三掌柜贈書活動第二十五期 網絡安全應急響應實戰

目錄 前言 網絡安全的重要性 關于《網絡安全應急響應實戰》 編輯推薦 內容簡介 作者簡介 圖書目錄 《網絡安全應急響應實戰》全書速覽 結束語 前言 在當今數字化時代&#xff0c;網絡安全已經成為企業和個人都無法忽視的重要問題。隨著網絡技術的飛速發展&#xff0c;…

車載軟件架構 --- 軟件開發面臨的問題

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 周末洗了一個澡,換了一身衣服,出了門卻不知道去哪兒,不知道去找誰,漫無目的走著,大概這就是成年人最深的孤獨吧! 舊人不知我近況,新人不知我過…

MySQL 8.0 OCP 1Z0-908 題目解析(31)

題目121 Choose two. Examine this command, which executes successfully on InnoDB Cluster: dba.dropMetadataSchema() Which two statements are true? □ A) The mysql_innodb_cluster_metadata schema is dropped from the instance where the connection was establish…

本地生活服務 app 同城信息發布系統搭建

一、邏輯分析用戶需求層面&#xff1a;對于發布者來說&#xff0c;需要一個便捷的界面來輸入同城信息&#xff0c;包括但不限于房屋租售、招聘求職、二手交易、活動推廣等各類信息。發布者要能夠上傳相關圖片、詳細描述信息內容、設置價格&#xff08;如果有需要&#xff09;、…

[Python] -項目實戰4- 利用Python進行Excel批量處理

一、為什么要批量處理Excel文件? 節省時間:人工對數十、數百個 Excel 文件重復操作不現實,Python 批量處理一次搞定。 保證一致性:統一格式、統一操作,避免手動誤差。 易于集成:可嵌入日常自動化流程,支持定時和觸發執行。 二、常用庫及選型建議 庫 作用 優勢 局限 p…

社區搜索離線回溯系統設計:架構、挑戰與性能優化|得物技術

一、項目背景在社區場景中&#xff0c;我們積累了豐富的用戶互動數據。這些歷史互動信息對CTR/CVR預估建模具有重要參考價值&#xff0c;用戶的每次互動都反映了其特定維度的偏好特征。當前&#xff0c;已在多個業務實踐中驗證&#xff0c;基于用戶歷史互動特征進行未來行為預測…

WPF——自定義ListBox

在閱讀本文前&#xff0c;最好先看看WPF——自定義RadioButton 背景 WPF中實現單選功能通常有兩種方案&#xff1a; - RadioButton組&#xff1a;傳統方案&#xff0c;但代碼冗余 - ListBox定制&#xff1a;通過樣式改造&#xff0c;兼顧數據綁定和UI靈活性 需求 一組選項中…

rancher上使用rke在華為云多網卡的服務器上安裝k8s集群問題處理了

報錯:問題&#xff1a;[[network] Host [192.168.0.213] is not able to connect to the following ports: [192.168.0.213:2379]. Please check network policies and firewall rules]問題&#xff1a; roothwy-isms-210-66:~# gotelnet 172.17.210.66 2379 map[2379:failed] …

xformers包介紹及代碼示例

文章目錄主要特性安裝方式主要優勢使用場景注意事項代碼示例xFormers是由Meta開發的一個高性能深度學習庫&#xff0c;專門用于優化Transformer架構中的注意力機制和其他組件。它提供了內存高效和計算高效的實現&#xff0c;特別適用于處理長序列和大規模模型。github地址&…

CityEngine自動化建模

CityEngine學習記錄 學習網址&#xff1a; 百度安全驗證 CityEngine-CityEngine_Rule-based_Modeling-基于規則建模和輸出模型 - 豆丁網 CityEngine 初探-CSDN博客 City Engine CGA 規則包_cga規則-CSDN博客 CityEngine學習記錄 學習網址&#xff1a;百度安全驗證 CityE…

Nacos+LoadBalancer實現服務注冊與發現

目錄 一、相關文章 二、兼容說明 三、服務注冊到Nacos 四、服務發現 五、服務分級存儲模型 六、查看集群服務 七、LoadBalancer負載均衡 一、相關文章 基礎工程&#xff1a;gradle7.6.1springboot3.2.4創建微服務工程-CSDN博客 Nacos服務端安裝&#xff1a;Nacos服務端…

事務并發-封鎖協議

事務并發數據庫里面操作的是事務。事務特性&#xff1a;原子性&#xff1a;要么全做&#xff0c;要么不做。一致性&#xff1a;事務發生后數據是一致的。隔離性&#xff1a;任一事務的更新操作直到其成功提交的整個過程對其他事務都是不可見的&#xff0c;不同事務之間是隔離的…

大氣波導數值預報方法全解析:理論基礎、預報模型與誤差來源

我們希望能夠像天氣預報一樣&#xff0c;準確預測何時、何地會出現大氣波導&#xff0c;其覆蓋范圍有多大、持續時間有多長&#xff0c;以便為通信、雷達等應用提供可靠的環境保障。 目錄 &#xff08;一&#xff09;氣象預報 1.1 氣象預報的分類 1.2 大氣數值預報基礎 1.2…