天天看點

Java高性能程式設計之NIO三大核心理念NIO三大核心理念

NIO三大核心理念

首先介紹NIO中三個核心元件

  • Buffer緩沖區
  • Channel通道
  • Selector選擇器

一、Buffer緩沖區

Java高性能程式設計之NIO三大核心理念NIO三大核心理念

1.Buffer 三個重要屬性:

  • capacity容量:作為一個記憶體塊,Buffer具有一定的固定大小,也成為“容量”
  • position位置:寫入模式時代表寫資料的位置。讀取模式時,代表讀取資料的位置
  • limit限制:寫入模式,限制等于buffer的容量。讀取模式下,limit等于寫入的資料量

    //注意區分不同模式下的含義。

2. ByteBuffer記憶體類型

  • 直接記憶體(direct堆外記憶體):在JVM之外向實體記憶體直接申請記憶體

    進行IO或檔案IO時比heapBuffer少一次拷貝

ByteBuffrt directByteBuffer = ByteBuffer.allocateDirect(noBNytes);

優點:

1、進行IO或檔案IO時比heapBuffer少一次拷貝。(file/socket -> OS memory -> jvm heap)

2、在GC範圍之外,降低GC壓力,但實作了自動管理。DirextByteBuffer類提供Cleaner對象(PhantomReference),Cleaner被GC前會執行clean方法,觸發DirectByteBuffer中定義的Deallocator。

  • 非直接記憶體(heap堆記憶體):在JVM的申請記憶體

建議:性能确實可觀的時候才去使用;配置設定給大型、長壽命;(網絡傳輸、檔案讀寫場景)

通過虛拟機參數MaxDirectMemorySize限制大小,防止耗盡整個機器記憶體

二、Channel: 通道

和标準的IO Stream差別:在一個通道内進行讀取和寫入時stream通常是單向的(input和output),可以非阻塞讀取和寫入通道,通道始終讀取或寫入緩沖區,channel的API涵蓋了UDP/TCP網絡和檔案IO。(FileCjannel,DatagramCjannel,SocketChannel,ServerSocketChannel)

SocketChannel:用于建立TCP連接配接,類似java.net.Socket.有兩種建立的方式:

1、用戶端主動發起和服務的連接配接。

2、服務端擷取新的連接配接

  • SockerChannel:用戶端

//用戶端主動發起連接配接的方式

SocketChannel socketChannel = SocketChannel.open();

//設定為非阻塞模式

socketChannel.configureBlocking(false);

//建立一個端口和ip

socketChannel.connect(new InetSocketAddress(“htttp:163.com”,80));

//發送請求資料 - 向通道寫入資料

socketChannel.write(byteBuffer);

//讀取服務端傳回 - 讀取緩沖區的資料

int butesRead = socketChannel.read(byteBuffer);

//關閉連接配接

socketChannel.close();

write寫:非阻塞,write()在尚未寫入任何内容可能就傳回了。需要在循環中調用

read讀:非阻塞,read()方法可能直接傳回而根本不讀取任何資料,根據傳回的int值判斷讀取了多少位元組

  • ServerSocketChannel:服務端

//建立網絡服務端

ServerSocketChannel serverSockerChannel = ServerSocketChannel.open();

//設為非阻塞模式

serverSocletChannel.configureBlocking(false);

//綁定端口

serverSocletChannel.socket().bind(new InetSocketAddress(8080));

while(true){

SocketChannel soccketChannel = serverSocletChannel.accept();

if(socketChannel != null){

//TCP請求 讀取/響應

}

}

注:serverSocletChannel.accept()如果該通道處于非阻塞,如果沒有挂起的連接配接則該方法立即傳回null。

是以必須檢查傳回的對象是否為空

三、Selector:選擇器

  • Selector是一個javaNIO 元件,可以檢查一個或多個NIO通道,并确定哪些通道已經準備好進行讀取或寫入。實作單個線程可以管理多個通道,進而管理多個網絡連接配接。核心概念是事件驅動機制。
  • 一個線程使用Selector監聽多個channel的不同僚件:

    四種事件分别對應SelectionKey四個常量:

Connect:連接配接(Selector.OP_CONNECT)
    用戶端與服務端建立連接配接,用戶端觸發事件
    Accept: 準備就緒(OP_ACCEPT)
    服務端檢測到用戶端連接配接請求,服務端觸發事件
    Read:   讀取(OP_READ)
    用戶端與服務端建立連接配接之後讀取操作,雙端觸發事件
    Write:  寫入(OP_WRITE)
    用戶端與服務端建立連接配接之後寫入操作,雙端觸發事件
           

NIO對比BIO

Java高性能程式設計之NIO三大核心理念NIO三大核心理念

四、NIO與多線程結合的改進方案

  • mainReactor接收->分發給subReactor讀寫->具體業務邏輯分發給單獨的線程池處理

總結

NIO應用于網絡應用開發還是比較繁瑣,要想将性能提升,還需要和多線程技術結合起來。
因為網絡程式設計本身的複雜性,以及JDK API開發的使用難度較高, 是以在開源社群中,湧出
來很多對JDK NIO進行封裝、增強後的網絡程式設計架構,例如:Netty、Mina等。
           

繼續閱讀