亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

非阻塞 Java NIO Channel 體系介紹

1. 前言

java.nio.channels.SocketChannel 和 java.nio.channels.ServerSocketChannel 是編寫非阻塞 Java TCP Soccket 程序的重要模塊。然而,Channel 是 Java NIO 非常重要的概念,在 java.nio.channels 抽象了完整的、關于 Channel 的接口(Interface) 層次結構。

Channel 表示一個和硬件設備、磁盤文件、網絡 Socket 等 I/O 設備、或者組件之間連接。Channel 的狀態要么是打開的,要么是關閉的。當 Channel 處于打開狀態,可以從 Channel 中讀取數據并且保存到 ByteBuffer 中,也可以將 ByteBuffer 中的數據寫到 Channel 中。當 Channel 處于關閉狀態,對 Channel 執行讀、寫操作,會產生 ClosedChannelException 異常。

2. Channel 類層次結構

java.nio.channels 包抽象了完整的 Channel 層次結構,如下圖所示:

圖片描述

2.1 Java NIO Channel 的祖先類

java.nio.channels.Channel 是一個 Java 接口,是整個 Channel 家族的祖先,聲明的接口如下:

// 獲取 Channel 的狀態
public boolean isOpen();
// 關閉 channel
public void close() throws IOException;

Java NIO Channel 具有以下特性:

  • Java NIO 支持面向字節流的數據讀寫方式,數據從 ByteBuffer 讀取后寫到 Channel 中,或者從 Channel 中讀取后寫入 ByteBuffer 中。
  • Java NIO Channel 支持字節流讀寫雙向操作,一個處于 Open 狀態的 Channel,既可以進行讀操作、也可以進行寫操作。
  • Java NIO Channel 支持阻塞和非阻塞兩種模式。
  • Java NIO Channel 是線程安全的。

2.2 Java NIO 中其他 Channel 接口

在 Java NIO Channel 體系中,對于 Socket 的抽象、數據讀、數據寫、數組形式的多緩沖讀、數組形式的多緩沖寫等功能分別進行了抽象,每一個功能都對應一個 Java 接口,下來我們分別做一個說明。

java.nio.channels.ReadableByteChannel 是一個 Java Interface,是對 Channel 讀操作的抽象,聲明的接口如下:

public int read(ByteBuffer dst) throws IOException;

Channel 的 read 方法是從 I/O 設備讀取數據,保存在 ByteBuffer 中,為此調用者必須提供 ByteBuffer 用以保存數據。返回值是讀取的字節數、0、或者 -1。如果是阻塞式 Channel,read 至少返回 1 或者 -1;如果是非阻塞式 Chanel,read 可能會返回 0。

java.nio.channels.WritableByteChannel 是一個 Java Interface,是對 Channel 寫操作的抽象,聲明的接口如下:

public int write(ByteBuffer src) throws IOException;

Channel 的 write 方法是從 ByteBuffer 讀取數據,寫入 I/O 設備中,為此調用者必須將要寫出去的數據保存到 ByteBuffer 中。返回值是寫入的字節數、0、或者 -1。如果是阻塞式 Channel,write 返回請求寫入的字節數 或者 -1;如果是非阻塞式 write 可能會返回 0。

java.nio.channels.GatheringByteChannel 是一個 Java Interface,是對 Channel 寫操作的抽象,可以寫入一個數組,支持對多個 ByteBuffer 的寫入,聲明的接口如下:

public long write(ByteBuffer[] srcs, int offset, int length)
        throws IOException;
public long write(ByteBuffer[] srcs) throws IOException;

java.nio.channels.ScatteringByteChannel 是一個 Java Interface,是對 Channel 讀操作的抽象,可以讀入一個數組,支持對多個 ByteBuffer 的讀入,聲明的接口如下:

public long read(ByteBuffer[] dsts, int offset, int length)
        throws IOException;
public long read(ByteBuffer[] dsts) throws IOException;        

java.nio.channels.NetworkChannel 是一個 Java Interface,表示一個 Socket。實現此接口的 Channel 表示對 Socket 的封裝。

java.nio.channels.SelectableChannel 是一個 Java Interface,用于和 java.nio.channels.Selector 集成。聲明的主要接口如下:

public abstract SelectableChannel configureBlocking(boolean block)
        throws IOException;
public final SelectionKey register(Selector sel, int ops)
        throws ClosedChannelException

實現了 SelectableChannel 接口的類,可以將 I/O 操作設置為非阻塞模式,同時可以注冊到 Selector,通過 I/O 多路復用機制監聽事件。

java.nio.channels.ByteChannel 也是一個 Java 接口,只是實現了 java.nio.channels.ReadableByteChannel 和 java.nio.channels.WritableByteChannel 兩個接口。ByteChannel 本身沒有聲明任何接口,實現了讀寫聚合的功能。

3. Channel 實現類

在 Channel 的類的層次結構圖中,我們畫出四個常用的實現類如下:

  • FileChannel

    文件 Channel 類是對磁盤文件的抽象,可以讀寫磁盤文件數據。需要通過 FileInputStream 的 getChannel 方法創建 FileChannel 的對象,你不可以直接創建 FileChannel 的對象。FileChannel 對象的創建方法如下:

FileInputStream inFile = new FileInputStream("D:\\fileChannelTest.txt");
ReadableByteChannel fileChannel = inFile.getChannel();  
  • DatagramChannel

    數據報 Channel 是用于抽象 UDP Socket,可以將 UDP 數據的讀寫集成到 Selector 機制中。DatagramChannel 對象的創建方法:

DatagramChannel ch = DatagramChannel.open();  
  • SocketChannel 是對 TCP 的抽象,用于讀寫 TCP 數據,用于 TCP 客戶端和服務器端

  • ServerSocketChannel 是對 TCP 監聽 Socket 的抽象,用于 TCP 服務器的創建。

4. 總結

本節重點是對 Java NIO Channel 類的體系結構進行了介紹。通過 channel 類的體系結構圖,我們可以看出,主要是對數據讀、數據寫、數組形式的多緩沖讀、數組形式的多緩沖寫、以及和多路復用機制 Selector的集成等功能的抽象。每一個接口都對應了相應功能的實現,將這些接口進行一個組合,就是一個具體的 I/O 功能的實現,這一具體的組合是通過具體實現類來體現的。比如 ,FileChannel 是對磁盤文件的抽象,DatagramChannel 是對 UDP Socket 的抽象,Socket Channel 是對 TCP Socket 的抽象,ServerSocketChannel 是對 TCP Server 監聽邏輯的抽象。

通過逐個分析每一個接口所提供的能力,我們就熟悉了完整的 Java NIO Channel 體系。