摘要:該線程在此期間不能再干任何事情了。線程通訊線程之間通過等方式通訊。選擇器傳統的模式會基于服務器會為每個客戶端請求建立一個線程由該線程多帶帶負貴處理一個客戶請求。
本文是對NIO知識的歸納與整理
1.阻塞與同步1)阻塞(Block)和非租塞(NonBlock):
阻塞和非阻塞是進程在訪問數據的時候,數據是否準備就緒的一種處理方式,當數據沒有準備的時候阻塞:往往需要等待缞沖區中的數據準備好過后才處理其他的事情,否則一直等待在那里。
非阻塞:當我們的進程訪問我們的數據緩沖區的時候,如果數據沒有準備好則直接返回,不會等待。如果數據已經準備好,也直接返回
2)同步(Synchronization)和異步(Async)的方式:
同步和異步都是基于應用程序私操作系統處理IO事件所采用的方式,比如同步:是應用程序要直接參與IO讀寫的操作。異步:所有的IO讀寫交給搡作系統去處理,應用程序只需要等待通知。
同步方式在處理IO事件的時候,必須阻塞在某個方法上靣等待我們的IO事件完成(阻塞IO事件或者通過輪詢IO事件的方式).對于異步來說,所有的IO讀寫都交給了搡作系統。這個時候,我們可以去做其他的事情,并不拓要去完成真正的IO搡作,當搡作完成IO后.會給我們的應用程序一個通知
同步:阻塞到IO事件,阻塞到read成則write。這個時候我們就完全不能做自己的事情,讓讀寫方法加入到線程里面,然后阻塞線程來實現,對線程的性能開銷比較大,
2.BIO與NIO對比block IO與Non-block IO
1)區別
IO模型IONIO
方式從硬盤到內存從內存到硬盤
通信面向流(鄉村公路)面向緩存(高速公路,多路復用技術)
處理阻塞IO(多線程)非阻塞IO(反應堆Reactor)
觸發無選擇器(輪詢機制)
2)面向流與面向緩沖
Java NIO和IO之間第一個最大的區別是,IO是面向流的.NIO是面向緩沖區的。Java IO面向流意味著毎次從流中讀一個成多個字節,直至讀取所有字節,它們沒有被緩存在任何地方,此外,它不能前后移動流中的數據。如果需要前后移動從流中讀取的教據,需要先將它緩存到一個緩沖區。Java NIO的緩沖導向方法略有不同。數據讀取到一個它稍后處理的緩沖區,霱要時可在緩沖區中前后移動。這就增加了處理過程中的靈活性。但是,還需要檢查是否該緩沖區中包含所有您需要處理的數裾。而且,需確保當更多的數據讀入緩沖區時,不要覆蓋緩沖區里尚未處理的數據。
3)阻塞與非阻塞
Java IO的各種流是阻塞的。這意味著,當一個線程調用read() 或 write()時,該線程被阻塞,直到有一些數據被讀取,或數據完全寫入。該線程在此期間不能再干任何事情了。 Java NIO的非阻塞模式,使一個線程從某通道發送請求讀取數據,但是它僅能得到目前可用的數據,如果目前沒有數據可用時,就什么都不會獲取。而不是保持線程阻塞,所以直至數據變的可以讀取之前,該線程可以繼續做其他的事情。 非阻塞寫也是如此。一個線程請求寫入一些數據到某通道,但不需要等待它完全寫入,這個線程同時可以去做別的事情。 線程通常將非阻塞IO的空閑時間用于在其它通道上執行IO操作,所以一個多帶帶的線程現在可以管理多個輸入和輸出通道(channel)。
4)選擇器(Selector)
Java NIO的選擇器允許一個多帶帶的線程來監視多個輸入通道,你可以注冊多個通道使用一個選擇器,然后使用一個多帶帶的線程來“選擇"通道:這些通里已經有可以處理的褕入,或者選擇已準備寫入的通道。這選懌機制,使得一個多帶帶的線程很容易來管理多個通道。
5)NIO和BIO讀取文件
BIO讀取文件
BIO從一個阻塞的流中一行一行的讀取數據
NIO讀取文件
通道是數據的載體,buffer是存儲數據的地方,線程每次從buffer檢查數據通知給通道
6)處理數據的線程數
NIO:一個線程管理多個連接
BIO:一個線程管理一個連接
3.NIO簡介在Java1.4之前的I/O系統中,提供的都是面向流的I/O系統,系統一次一個字節地處理數據,一個輸入流產生一個字節的數據,一個輸出流消費一個字節的數據,面向流的I/O速度非常慢,而在Java 1.4中推出了NIO,這是一個面向塊的I/O系統,系統以塊的方式處理處理,每一個操作在一步中產生或者消費一個數據庫,按塊處理要比按字節處理數據快的多。
在NIO中有幾個核心對象需要掌握:緩沖區(Buffer)、通道(Channel)、選擇器(Selector)。
4.緩沖區Buffer緩沖區實際上是一個容器對象,更直接的說,其實就是一個數組,在NIO庫中,所有數據都是用緩沖區處理的。在讀取數據時,它是直接讀到緩沖區中的; 在寫入數據時,它也是寫入到緩沖區中的;任何時候訪問 NIO 中的數據,都是將它放到緩沖區中。而在面向流I/O系統中,所有數據都是直接寫入或者直接將數據讀取到Stream對象中。
在NIO中,所有的緩沖區類型都繼承于抽象類Buffer,最常用的就是ByteBuffer,對于Java中的基本類型,基本都有一個具體Buffer類型與之相對應,它們之間的繼承關系如下圖所示:
1)其中的四個屬性的含義分別如下:
容量(Capacity):緩沖區能夠容納的數據元素的最大數量。這一個容量在緩沖區創建時被設定,并且永遠不能改變。
上界(Limit):緩沖區的第一個不能被讀或寫的元素。或者說,緩沖區中現存元素的計數。
位置(Position):下一個要被讀或寫的元素的索引。位置會自動由相應的 get( )和 put( )函數更新。
標記(Mark):下一個要被讀或寫的元素的索引。位置會自動由相應的 get( )和 put( )函數更新。
2)Buffer的常見方法如下所示:
flip(): 寫模式轉換成讀模式
rewind():將 position 重置為 0 ,一般用于重復讀。
clear() :
compact(): 將未讀取的數據拷貝到 buffer 的頭部位。
mark(): reset():mark 可以標記一個位置, reset 可以重置到該位置。
Buffer 常見類型: ByteBuffer 、 MappedByteBuffer 、 CharBuffer 、 DoubleBuffer 、 FloatBuffer 、 IntBuffer 、 LongBuffer 、 ShortBuffer 。
3)基本操作
Buffer基礎操作: 鏈接
緩沖區分片,緩沖區分配,直接緩存區,緩存區映射,緩存區只讀:鏈接
4)緩沖區存取數據流程
存數據時position會++,當停止數據讀取的時候
調用flip(),此時limit=position,position=0
讀取數據時position++,一直讀取到limit
clear() 清空 buffer ,準備再次被寫入 (position 變成 0 , limit 變成 capacity) 。
5.通道Channel通道是一個對象,通過它可以讀取和寫入數據,當然了所有數據都通過Buffer對象來處理。我們永遠不會將字節直接寫入通道中,相反是將數據寫入包含一個或者多個字節的緩沖區。同樣不會直接從通道中讀取字節,而是將數據從通道讀入緩沖區,再從緩沖區獲取這個字節。
在NIO中,提供了多種通道對象,而所有的通道對象都實現了Channel接口。它們之間的繼承關系如下圖所示:
1)使用NIO讀取數據
在前面我們說過,任何時候讀取數據,都不是直接從通道讀取,而是從通道讀取到緩沖區。所以使用NIO讀取數據可以分為下面三個步驟:
從FileInputStream獲取Channel
創建Buffer
將數據從Channel讀取到Buffer中
2)使用NIO寫入數據
使用NIO寫入數據與讀取數據的過程類似,同樣數據不是直接寫入通道,而是寫入緩沖區,可以分為下面三個步驟:
從FileInputStream獲取Channel
創建Buffer
將數據從Channel寫入到Buffer中
6.反應堆1)阻塞IO模型
在老的IO包中,serverSocket和socket都是阻塞式的,因此一旦有大規模的并發行為,而每一個訪問都會開啟一個新線程。這時會有大規模的線程上下文切換操作(因為都在等待,所以資源全都被已有的線程吃掉了),這時無論是等待的線程還是正在處理的線程,響應率都會下降,并且會影響新的線程。
2)NIO
Java NIO是在jdk1.4開始使用的,它既可以說成“新IO”,也可以說成非阻塞式I/O。下面是java NIO的工作原理:
1.由一個專門的線程來處理所有的IO事件,并負責分發。
2.事件驅動機制:事件到的時候觸發,而不是同步的去監視事件。
3.線程通訊:線程之間通過wait,notify等方式通訊。保證每次上下文切換都是有意義的。減少無謂的線程切換。
注:每個線程的處理流程大概都是讀取數據,解碼,計算處理,編碼,發送響應。
7.選擇器傳統的 server / client 模式會基于 TPR ( Thread per Request ) .服務器會為每個客戶端請求建立一個線程.由該線程多帶帶負貴處理一個客戶請求。這種模式帶未的一個問題就是線程數是的劇增.大量的線程會增大服務器的開銷,大多數的實現為了避免這個問題,都采用了線程池模型,并設置線程池線程的最大數量,這又帶來了新的問題,如果線程池中有 200 個線程,而有 200 個用戶都在進行大文件下載,會導致第 201 個用戶的請求無法及時處理,即便第 201 個用戶只想請求一個幾 KB 大小的頁面。傳統的 Sorvor / Client 模式如下圍所示:
NIO 中非阻塞IO采用了基于Reactor模式的工作方式,IO調用不會被阻塞,相反是注冊感興趣的特點IO事件,如可讀數據到達,新的套接字等等,在發生持定率件時,系統再通知我們。 NlO中實現非阻塞IO的核心設計Selector,Selector就是注冊各種IO事件的地方,而且當那些事件發生時,就是這個對象告訴我們所發生的事件。
當有讀或者寫等任何注冊的事件發生時,可以從Selector中獲得相應的SelectionKey,同時從SelectionKey中可以找到發生的事件和該事件所發生的具體的SelectableChannel,以獲得客戶端發送過來的數據。
使用NIO中非阻塞IO編寫服務器處理程序,有三個步驟
1.向Selector對象注冊感興趣的事件
2.從Selector中獲取感興趣的事件
3.根據不同事件進行相應的處理
8.NIO源碼分析Selector是NIO的核心
epool模型
1)Selector
Selector的open
2)ServerSocketChannel
ServerSocketChannel.open
9.AIOAsynchronous IO
異步非阻塞IO
BIO ServerSocket
NIO ServerSocketChannel
AIO AsynchronousServerSocketChannel
AIO通信
看完本文的同學都掌握了嗎,還沒掌握的同學可以收藏喲,也可以轉給其他需要的同學。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74473.html
閱讀 1141·2021-11-23 10:04
閱讀 2401·2021-11-22 15:29
閱讀 2743·2021-11-19 09:40
閱讀 715·2021-09-22 15:26
閱讀 2117·2019-08-29 16:27
閱讀 2484·2019-08-29 16:10
閱讀 1918·2019-08-29 15:43
閱讀 3275·2019-08-29 12:43