摘要:操作系統是能夠獲取到事件操作完成的事件,基于回調函數機制和操作系統的操作控制實現事件檢測機制。
前面的文章NIO基礎知識介紹了Java NIO的一些基本的類及功能說明,Java NIO是用來替換java 傳統IO的,NIO的一些新的特性在網絡交互方面會更加的明顯。
Java 傳統IO的弊端????“基于JVM來實現每個通道的輪詢檢查通道狀態的方法是可行的,但仍然是有問題的,檢查每個通道是否就緒是至少需要一次系統調用,執行的代價是非常昂貴的。同時這種檢查不是原子的。列表中的每個通道在檢查之后狀態變成就緒,但需要等到下一次輪詢之前JVM是無法感知的。最糟糕的是,JVM除了不斷遍歷列表之外將別無選擇。JVM無法在某通道就緒時直接得到通知。
????這就是為什么監控多個socket連接的傳統的java方案是:為每個socket創建一個線程并使線程可以再read()調用中阻塞,直到數據可用。這實際上將每個阻塞在對應socket上的線程當做了socket事件監控器,并將JVM的線程調度當做了事件通知。但是線程的阻塞和JVM的線程調用都是為了這種目的而設計的。當線程數量增長失控時,JVM為了管理這些線程,導致程序性能降低。”--摘自《JAVA NIO》
上述兩段話摘自《JAVA NIO》第四章-選擇器中,主要闡述了java 傳統NIO的基本實現和弊端。通過上述文字我們也知道了,提高傳統IO的性能可以從兩方面入手:1.減少線程數量 2.實時獲取IO事件。
傳統I/O為了能實時獲取I/O事件,所以才會給每個socket連接分配一個線程用于監控socket事件,因為如何獲取I/O事件通知是關鍵。因此調整JVM的I/O模型是提高I/O性能關鍵。
我們來了解下I/O模型的類型:
單線程阻塞I/O模型
只能同時處理一個客戶端請求,并且在I/O操作上是阻塞的,服務端線程會一直等待I/O操作完成,不會做其他的事情。服務端讀取客戶端數據時要等待客戶端發送數據并且操作系統內核復制到用戶進程中之后才解除阻塞狀態;服務端寫數據回客戶端是要等待用戶進程將數據寫入內核并發送到客戶端后才解除阻塞狀態。單線程阻塞I/O模型無法同時處理多個連接,只能串行處理連接。整個運行過程都只有一個線程,服務端系統資源消耗較小,但并發能力低。
多線程阻塞I/O模型
利用多線程機制為每個客戶端分配一個線程,每個線程執行讀取客戶端的數據或數據成功寫入客戶端后才解除阻塞狀態。支持多個客戶端并發響應,處理能力得到提高。系統資源消耗較大,多線程之間會產生線程切換成本,同時為了實現線程安全引入線程同步機制導成程序結構復雜。
單線程非阻塞I/O模型
在調用讀寫接口后立即返回,而不會進入阻塞狀態;基于事件檢測機制獲取到事件發生,進行對應事件的I/O操作。
事件檢測方式:
應用程序遍歷套接字的事件檢測
服務端程序會保存一個socket套接字連接列表,應用層線程對socket套接字列表輪詢嘗試讀取或寫入。如果嘗試失敗,則在下一個循環再繼續嘗試。查詢每個socket套接字都至少需要一次系統調用,而且無法立即獲取socket套接字狀態。同時應用程序除了要遍歷socket套接字列表之外,還需要處理數據的拼接,實際會占用較多的CPU資源
內核遍歷套接字的事件檢測
將遍歷socket列表的工作交給操作系統內核,應用層向發去操作系統內核請求讀寫列表。操作系統內核會遍歷所有套接字并生成對應的可讀列表readList和可寫列表writeList返回給應用程序。應用程序獲取到具體socket,對每個socket進行相應的I/O操作。
應用程序向內核請求讀寫列表,內核遍歷所有的套接字并生成對應的可讀列表readList和可寫列表writeList。readList標明了每個套接字是否可讀,例如套接字2、套接字3的值為1表示可讀,套接字1的值為0表示不可讀;同樣,writeList表示套接字是否可寫。
內核基于事件回調的事件檢測
遍歷套接字列表是個效率比較低的方式,無論是在內核層還是在應用層。操作系統是能夠獲取到I/O事件操作完成的事件,基于回調函數機制和操作系統的I/O操作控制實現事件檢測機制。
基于回調機制的完全套接字可讀可寫列表
用可讀列表readList和可寫列表writeList標記讀寫事件,套接字的數量與readList和writeList兩個列表的長度一樣。readList元素為1表示可讀,writeList元素為1表示可寫。當客戶端發送數據到服務端,內核完成從網卡復制數據調用回調函數將對應套接字readList中的元素置為1;若套接字已經做好寫操作準備,內核會將套接字對應writeList中的元素置為1。應用程序發送請求讀、寫事件列表,內核會把包含readList和writeList的事件列表返回給應用程序,應用程序分別遍歷列表,進而記性讀寫操作。
基于回調機制的部分套接字事件列表
如果套接字數量變大,事件列表傳輸也是不小的開銷。可以讓應用層告訴內核每個套接字感興趣的事件,當客戶端發送數據過來時,內核完成從網卡復制后即調用回調函數將套接字相關信息封裝成可讀事件event放到事件列表中;同樣,內核發現網卡可寫時會將套接字相關信息封裝成可寫事件event添加到事件列表中,事件列表中只有處于ready狀態的那部分套接字對應的事件。java NIO即是采用這種事件檢測機制,在客戶端連接大多數處于活躍的情況下,服務端只用一個線程一直循環處理這些連接,很好地利用了I/O操作的阻塞時間,提高了線程執行效率。
多線程非阻塞I/O模型
單線程非阻塞I/O已經大大提高了機器的執行效率,在多核機器上為了更好的提高CPU的使用率可以引入多線程。引入reactor線程模型,每個線程處理不同類型的事件連接。
NIO網絡通信java NIO性能較java傳統IO有較大提升主要是在網絡交互中,通過Selector來管理客戶端的連接,應用程序將客戶端socket連接注冊到Selector對象上。當客戶端socket連接有數據準備就緒或連接準備好寫操作時,應用程序通過selector獲取到對應socket通道(Channel),應用程序通過Channel對socket進行讀寫操作。
NIO中服務端一個線程可以同時與多個客戶端連接進行讀寫交互;而傳統IO則是服務端的一個線程只能同時處理一個客戶端,I/O操作時,線程處于阻塞狀態。
Selector是SelectableChannel的多路復用選擇器,用于監控SelectableChannel的IO狀況的。在Selector定義為SelectableChannel定義了四種事件類型:
SelectionKey.OP_READ????????讀事件
SelectionKey.OP_WRITE???????寫事件
SelectionKey.OP_CONNECT????接收到客戶端的連接事件
SelectionKey.OP_ACCEPT??????接收到客戶端的請求事件
多個事件之間用“|”連接
當服務端線程注冊事件發生時,操作系統內核會通過回調函數將該事件放到讀寫事件列表中。JVM通過Selector的select方法會獲取到已經注冊到Selector對象上的事件列表。若沒有事件發生select方法會一直阻塞知道有注冊的時間發生才會把發生的時間返回給Selector對象。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68649.html
摘要:而我們現在都已經發布了,的都不知道,這有點說不過去了。而對一個的讀寫也會有響應的描述符,稱為文件描述符,描述符就是一個數字,指向內核中的一個結構體文件路徑,數據區等一些屬性。 前言 只有光頭才能變強 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡單啦 本來我預想是先來回顧一下傳統的IO模式的,將傳統的IO模式的相關類理清楚(因為IO的類很多)。 但是,發現在整理的過程已...
摘要:當的數據準備好時,就會接到通知,得到那些已經準備好的數據。當與客戶端連接的數據沒有準備好時,會處于等待狀態不過幸好,用于管理的線程數是極少量的,而一旦有任何一個準備好了數據,就能立即得到通知,獲取數據進行處理。 java NIO是NEW IO的簡稱,它是一種可以替代javaIO的一套新的IO機制。它提供了一套不同java標準IO的操作機制。嚴格來說,NIO與并發并無直接關系。但是,使用...
摘要:最近在學習網絡編程和相關的知識,了解到是模式的網絡框架,但是提供了不同的來支持不同模式的網絡通信處理,包括同步異步阻塞和非阻塞。因為的版本使用的的模式,而則希望使用模式,而且版本沒有將的部分配置項暴露出來,比如說和。 ??最近在學習Java網絡編程和Netty相關的知識,了解到Netty是NIO模式的網絡框架,但是提供了不同的Channel來支持不同模式的網絡通信處理,包括同步、異步、...
摘要:的選擇器允許單個線程監視多個輸入通道。一旦執行的線程已經超過讀取代碼中的某個數據片段,該線程就不會在數據中向后移動通常不會。 1、引言 很多初涉網絡編程的程序員,在研究Java NIO(即異步IO)和經典IO(也就是常說的阻塞式IO)的API時,很快就會發現一個問題:我什么時候應該使用經典IO,什么時候應該使用NIO? 在本文中,將嘗試用簡明扼要的文字,闡明Java NIO和經典IO之...
摘要:從通道進行數據寫入創建一個緩沖區,填充數據,并要求通道寫入數據。三之通道主要內容通道介紹通常來說中的所有都是從通道開始的。從中選擇選擇器維護注冊過的通道的集合,并且這種注冊關系都被封裝在當中停止選擇的方法方法和方法。 由于內容比較多,我下面放的一部分是我更新在我的微信公眾號上的鏈接,微信排版比較好看,更加利于閱讀。每一篇文章下面我都把文章的主要內容給列出來了,便于大家學習與回顧。 Ja...
閱讀 1868·2021-11-22 09:34
閱讀 1141·2021-10-09 09:44
閱讀 3001·2021-09-29 09:35
閱讀 3617·2021-09-14 18:01
閱讀 1465·2021-08-16 10:49
閱讀 1084·2019-08-29 14:11
閱讀 849·2019-08-29 12:47
閱讀 3068·2019-08-26 13:47