第六課:NIO簡介

一、傳統BIO的缺點

BIO屬于同步阻塞行IO,在服務器的實現模型為,每一個連接都要對應一個線程。當客戶端有連接請求的時候,服務器端需要啟動一個新的線程與之對應處理,這個模型有很多缺陷。當客戶端不做出進一步IO請求的時候,服務器端的線程就只能掛著,不能去處理其他請求。這樣會對造成不必要的線程開銷。

二、阻塞與同步

同步和異步都是由基于應用程序和操作系統處理IO事件所采用的方式所決定的。
在這里插入圖片描述
阻塞和非阻塞式指線程在得到調用結果之前是否被掛起,主要針對線程。
在這里插入圖片描述

三、NIO簡介(同步非阻塞)

  • Java NIO全稱java non-blocking IO, 是指JDK提供的新API。從JDK1.4開始,Java提供了一系列改進的輸入/輸出的新特性,被統稱為NIO(即New IO),是同步非阻塞的。
  • NIO是一種面向緩沖區的、基于通道的IO操作,NIO有三大核心部分: Channel(通道), Buffer(緩沖區),Selector(選擇器)
  • java NIO的運行模式是:客戶端發送的鏈接請求都會被注冊到Selector(選擇器)上,多路復用器輪詢到有I/O請求時才會啟動一個線程去服務。

四、NIO三大核心原理

NIO有三大核心部分: Channel(通道), Buffer(緩沖區),Selector(選擇器)
Buffer(緩沖區)
緩沖區本質上就是一塊內存,數據的讀寫都是通過Buffer類實現的。緩沖區buffer主要是和通道數據交互,即從通道中讀入數據到緩沖區,和從緩沖區中把數據寫入到通道中,通過這樣完成對數據的傳輸。
Channel(通道)
java NIO的類似于流,但是又有些不同:既可以從通道中讀取數據,又可以寫數據到通道。但流的(input和output)讀寫通常是單向的。通道可以非阻塞讀取和寫入通道,通道可以支持讀取或寫入緩沖區,也支持異步讀寫。
Selector選擇器
Selector是一個java NIO組件,可以檢測一個或多個NIO通道,并確定已經準備好進行讀取或者寫入。這樣,一個單獨的線程就可以管理多個Channel,從而管理多個網絡連接,提高效率。
在這里插入圖片描述

  • 每個channel都會對應一個Buffer
  • 一個線程對應Selector,一個Selector對應多個Channel
  • 程序切換到那個channel是由事件決定
  • Selector會根據不同的事件,在各個通道上切換
  • Buffer就是一個內存塊,底層就是一個數組,數據的讀取和寫入都是通過Buffer來實現的

五、NIO三板斧

在這里插入圖片描述

六、NIO實現案例

客戶端

public class NioClient {public static void main(String[] args) throws IOException {SocketChannel socketChannel=SocketChannel.open();socketChannel.configureBlocking(false);InetSocketAddress address = new InetSocketAddress("127.0.0.1", 9000);if (!socketChannel.connect(address)) {while (!socketChannel.finishConnect()){System.out.println("連接中,客戶端可以進行其他工作");}String str="hello world!";ByteBuffer wrap = ByteBuffer.wrap(str.getBytes());socketChannel.write(wrap);//避免客戶端中斷System.in.read();}}
}

服務器端

public class NioServer {public static void main(String[] args) throws IOException {// 獲取一個ServerSocket通道ServerSocketChannel serverChannel = ServerSocketChannel.open();// serverChannel通道一直監聽9000端口serverChannel.socket().bind(new InetSocketAddress(9000));// 設置serverChannel為非阻塞serverChannel.configureBlocking(false);//創建Selector選擇器用來監聽通道Selector selector = Selector.open();// 把ServerSocketChannel注冊到selector中,并且selector對客戶端的連接操作感興趣SelectionKey selectionKey = serverChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服務啟動成功!");while(true){/** 如果事件沒有到達 selector.select() 會一直阻塞等待*/selector.select();Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()){SelectionKey key = iterator.next();if (key.isAcceptable()) // 如果是OP_ACCEPT事件,則進行連接獲取和事件注冊{ServerSocketChannel server = (ServerSocketChannel) key.channel(); //連接獲取SocketChannel socketChannel = server.accept(); // 連接獲取socketChannel.configureBlocking(false); // 設置為非阻塞SelectionKey selKey = socketChannel.register(selector, SelectionKey.OP_READ); //這里只注冊了讀事件,如果需要給客戶端寫數據,則需要注冊寫事件System.out.println("客戶端連接成功!");}else if(key.isReadable()) //如果是OP_READ事件,則進行讀取和打印{SocketChannel socketChannel = (SocketChannel) key.channel();ByteBuffer byteBuffer = ByteBuffer.allocate(128);int len = socketChannel.read(byteBuffer);if (len > 0) //如果有數據,則打印數據{System.out.println("接受到客戶端數據"+new String(byteBuffer.array()));}else if(len==-1) //如果客戶端斷開連接,關閉socket{System.out.println("客戶端斷開連接!");socketChannel.close();}}// 從事件集合中刪除本次處理的key,防止下次select重復處理iterator.remove();}}}
}

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

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

相關文章

《Spring Security 簡易速速上手小冊》第4章 授權與角色管理(2024 最新版)

文章目錄 4.1 理解授權4.1.1 基礎知識詳解授權的核心授權策略方法級安全動態權限檢查 4.1.2 主要案例&#xff1a;基于角色的頁面訪問控制案例 Demo 4.1.3 拓展案例 1&#xff1a;自定義投票策略案例 Demo測試自定義投票策略 4.1.4 拓展案例 2&#xff1a;使用方法級安全進行細…

【flutter】加載指示器(loading indicator)阻止用戶在某個操作執行期間操作頁面

在Flutter中&#xff0c;通過顯示一個加載指示器&#xff08;loading indicator&#xff09;來阻止用戶在某個操作執行期間操作頁面。以下是一個簡單的示例代碼&#xff0c;演示了按鈕被點擊后執行某操作&#xff0c;在操作完成前顯示加載指示器&#xff0c;阻止用戶操作頁面&a…

c語言數據結構(5)——棧

歡迎來到博主的專欄——C語言數據結構 博主id&#xff1a;代碼小豪 文章目錄 棧棧的順序存儲結構棧的插入空棧的初始化棧的刪除判斷空棧讀取棧頂元素數據 實現順序棧的所有代碼棧的鏈式存儲結構鏈式棧的初始化鏈式棧的入棧操作鏈式棧的出棧操作 實現鏈式棧的所有代碼 棧 棧是…

學習網絡編程No.11【傳輸層協議之UDP】

引言&#xff1a; 北京時間&#xff1a;2023/11/20/9:17&#xff0c;昨天成功更文&#xff0c;上周實現了更文兩篇&#xff0c;所以這周再接再厲。當然做題任在繼續&#xff0c;而目前做題給我的感覺以套路和技巧偏多&#xff0c;還是那句話很多東西不經歷你就是不懂&#xff…

測試人員如何向開發人員準確清晰地描述問題?

測試人員向開發人員準確清晰地描述問題可以采取以下方法&#xff1a; 提供詳細的背景和上下文信息&#xff1a;描述問題發生的環境、前提條件和操作步驟&#xff0c;讓開發人員能夠了解問題出現的場景。明確問題的癥狀和表現&#xff1a;清楚地說明問題的具體表現&#xff0c;…

【Python】2. 基礎語法

常量和表達式 我們可以把 Python 當成一個計算器, 來進行一些算術運算. 注意: print 是一個 Python 內置的 函數, 這個稍后詳細介紹. 可以使用 - * / ( ) 等運算符進行算術運算. 先算乘除, 后算加減. 運算符和數字之間, 可以沒有空格, 也可以有多個空格. 但是一般習慣上寫一…

LDR6328芯片:智能家居時代的小家電充電革新者

在當今的智能家居時代&#xff0c;小家電的供電方式正變得越來越智能化和高效化。 利用PD&#xff08;Power Delivery&#xff09;芯片進行誘騙取電&#xff0c;為后端小家電提供穩定電壓的技術&#xff0c;正逐漸成為行業的新寵。在這一領域&#xff0c;LDR6328芯片以其出色的…

Qt下使用modbus-c庫實現PLC線圈/保持寄存器的讀寫

系列文章目錄 提示&#xff1a;這里是該系列文章的所有文章的目錄 第一章&#xff1a;Qt下使用ModbusTcp通信協議進行PLC線圈/保持寄存器的讀寫&#xff08;32位有符號數&#xff09; 第二章&#xff1a;Qt下使用modbus-c庫實現PLC線圈/保持寄存器的讀寫 文章目錄 系列文章目錄…

前端Vue3項目如何打包成Docker鏡像運行

將前端Vue3項目打包成Docker鏡像并運行包括幾個主要步驟&#xff1a;項目打包、編寫Dockerfile、構建鏡像和運行容器。下面是一個基本的流程&#xff1a; 1. 項目打包 首先&#xff0c;確保你的Vue3項目可以正常運行和打包。在項目根目錄下執行以下命令來打包你的Vue3項目&am…

nest.js使用nest-winston日志一

nest-winston文檔 nest-winston - npm 參考&#xff1a;nestjs中winston日志模塊使用 - 浮的blog - SegmentFault 思否 安裝 cnpm install --save nest-winston winstoncnpm install winston-daily-rotate-file 在main.ts中 import { NestFactory } from nestjs/core; im…

【5G 接口協議】GTP-U協議介紹

博主未授權任何人或組織機構轉載博主任何原創文章&#xff0c;感謝各位對原創的支持&#xff01; 博主鏈接 本人就職于國際知名終端廠商&#xff0c;負責modem芯片研發。 在5G早期負責終端數據業務層、核心網相關的開發工作&#xff0c;目前牽頭6G算力網絡技術標準研究。 博客…

mysql學習

查看glibc版本 ldd --version --mysql啟動失敗,嘗試啟動 1 查看錯誤日志,端口被占用,參數名寫錯,有不支持的參數 2 通過mysqld啟動 mysqld --default-filemy.cnf & 3 mysqld --no-defaults --basedir/user/local/mysql --datadir/data/mysql/3306/data/ --usermysql 4 str…

深入理解 Nginx 的負載均衡與反向代理

深入理解 Nginx 的負載均衡與反向代理 Nginx 是一個高性能的 HTTP 和反向代理服務器&#xff0c;也是一個 IMAP/POP3/SMTP 代理服務器。由于其出色的性能和靈活性&#xff0c;Nginx 已成為現代 web 架構中的重要組成部分&#xff0c;尤其是在處理高并發連接和大規模流量時。在…

找到數組的中間位置-1991-[簡單]

力扣 關鍵點 從題目中總結出公式 sum * 2 nums[i] total從左往右開始嘗試&#xff0c;尋找 i 位置滿足上面的公式&#xff0c;為什么從左開始&#xff0c;因為題目要求找到最左邊的一個用前綴和的概念來解&#xff0c;從左往右嘗試i位置的左邊所有數之和&#xff0c;右邊所有…

基礎小白快速入門Python------>模塊的作用和意義

模塊&#xff0c; 這個詞聽起來是如此的高大威猛&#xff0c;以至于萌新小白見了瑟瑟發抖&#xff0c;本草履蟲見了都直搖頭&#xff0c;好像聽上去很難的樣子&#xff0c;但是但是&#xff0c;年輕人&#xff0c;請聽本少年細細講述&#xff0c;他只是看起來很難&#xff0c;實…

GO-接口

1. 接口 在Go語言中接口&#xff08;interface&#xff09;是一種類型&#xff0c;一種抽象的類型。 interface是一組method的集合&#xff0c;接口做的事情就像是定義一個協議&#xff08;規則&#xff09;&#xff0c;只要一臺機器有洗衣服和甩干的功能&#xff0c;我就稱它…

【go語言開發】swagger安裝和使用

本文主要介紹go-swagger的安裝和使用&#xff0c;首先介紹如何安裝swagger&#xff0c;測試是否成功&#xff1b;然后列出常用的注釋和給出使用例子&#xff1b;最后生成接口文檔&#xff0c;并在瀏覽器上測試 文章目錄 安裝注釋說明常用注釋參考例子 文檔生成格式化文檔生成do…

C++從零開始的打怪升級之路(day39)

這是關于一個普通雙非本科大一學生的C的學習記錄貼 在此前&#xff0c;我學了一點點C語言還有簡單的數據結構&#xff0c;如果有小伙伴想和我一起學習的&#xff0c;可以私信我交流分享學習資料 那么開啟正題 今天分享的是關于模板的知識點 1.非類型模板參數 模板參數分為…

大模型生成,Open API調用

大模型是怎么生成結果的 通俗原理 其實&#xff0c;它只是根據上文&#xff0c;猜下一個詞&#xff08;的概率&#xff09;…… OpenAI 的接口名就叫【completion】&#xff0c;也證明了其只會【生成】的本質。 下面用程序演示【生成下一個字】。你可以自己修改 prompt 試試…

高并發下的 AtomicReference 性能陷阱

介紹 Java 提供了 AtomicInteger/AtomicLong 在并發編程里經常用到&#xff0c;它們封裝了對 int 和 long 的原子操作。 Java 還提供了 AtomicReference&#xff0c;用于對象引用做原子性的管理&#xff0c;比如 get、set、CAS。 一般情況下 AtomicInteger、AtomicLong 的性能…