天天看點

java-NIO基礎

一、 Java NIO和傳統IO的對比

比對項 傳統IO NIO(Non-Block IO)
緩沖 面向流 面向塊(緩沖)
IO模型 阻塞IO 非阻塞IO
線程複用 選擇器

二、 java NIO類庫簡介

2.1 Buffer緩沖區(特點:面向塊)

傳統JavaIO是面向流的I/O。流I/O一次處理一個位元組。NIO則是面向塊的I/O,每次操作都是以資料塊為機關。它們的差距就好象兩個人吃飯,一個人一粒一粒的吃,另一個人狼吞虎咽,快慢顯而易見。NIO中引入了緩沖區(Buffer)的概念,緩沖區作為傳輸資料的基本機關:塊。Buffer緩沖區的引入,是NIO與傳統IO的一個重要差別.在傳統IO中,都是針對流資料的操作,在NIO中是針對緩沖區資料操作。

緩沖區的實質是一個數組,最常用的是ByteBuffer.事實上每一種java基本類型都對應一種緩沖區類型.

java-NIO基礎

2.2 Channel通道

Channel是資料通道,它與傳統IO Stream的主要差別在于通道是雙向讀寫的,流隻是朝着一個方向移動

Channel可以主要分為2大類:一類為網絡資料讀寫的SelectableChannel和檔案讀寫的FileChannel.

2.3 多路複用器選擇器Selector

Selector類是NIO的核心類,Selector能夠檢測多個注冊的通道上,是否有事件發生,如果有事件發生,便擷取事件然後針對每個事件進行相應的響應處理。這樣一來,隻是用一個單線程就可以管理多個通道,也就是管理多個連接配接。這樣使得隻有在連接配接真正有讀寫事件發生時,才會調用函數來進行讀寫,就大大地減少了系統開銷,并且不必為每個連接配接都建立一個線程,不用去維護多個線程,并且避免了多線程之間的上下文切換導緻的開銷。

2.4 檔案鎖定,記憶體映射等其他新特性

  • 檔案鎖定是多個程序協同工作的情況下,要協調程序間對共享資料的通路必不可少的工具。
  • 記憶體映射利用虛拟記憶體技術提供對檔案的高速緩存,使讀取磁盤檔案就像從記憶體中讀取一樣高效,但是卻不會有記憶體洩漏的危險,因為在記憶體中不會存在檔案的完整拷貝。

三、 IO模型

JDK4提供了非阻塞IO的能力,JDK7開始提供異步IO能力(NIO2.0)

3.1 阻塞I/O

  • 同步阻塞IO

在資料沒有讀寫完成之前,線程不可以進行下一步操作,這樣線程隻好眼睜睜的在那裡傻等。

下圖為采用阻塞IO的通訊模型的服務端,由一個Acceptor監聽用戶端的連結,它接收到用戶端的請求後建立一個新的線程進行鍊路處理,通過輸出流應答用戶端,線程銷毀。簡單地說就是,一用戶端請求對應一個線程.

java-NIO基礎

這個模型有一個很大的問題,就是當用戶端請求規模較大的時候,一用戶端請求建立一個線程,導緻伺服器資源消耗殆盡,造成當機。

  • 僞異步IO(線程池)

為了解決這個問題,在服務端使用線程池。線程的數量是固定的(線程池),使用的時候借用擷取,用完之後不是銷毀而是将線程歸還給線程池。但這個解決方案,在并發量超過線程池内現成的數量時,會導緻擷取線程的時間拉長,應答緩慢,延遲較大!這個方案,我們稱為"僞異步IO"!

java-NIO基礎

3.2 非阻塞I/O(Non-Block IO)

  • 傳統JavaIO是基于阻塞I/O模型的:當發起一個I/O請求時,如果資料沒有準備好(read時無可讀資料,write時資料不可寫入),那麼線程便會阻塞,直到資料準備好,導緻線程大部分的時間都在阻塞。
  • 非阻塞I/O則允許線程在有資料的時候處理資料,沒有資料的時候釋放CPU資源,提高了資源使用率。在資料沒有準備好之前,調用線程可以離開,隻需要每隔一段時間回來詢問一次。

3.3 異步I/O

在資料沒有讀寫完成之前,調用線程可以離開也不用輪詢。在資料準備好之後,多路複用監聽會主動通知調用線程。這通常需要複雜的設計,為降低NIO與AIO的實作複雜度,我們可以使用Netty或者mina等架構。

java-NIO基礎

喜歡 (9)or分享 (0)