1. 程式人生 > >JAVA 非阻塞IO原理

JAVA 非阻塞IO原理

1.  基本概念

IO是主存和外部裝置(硬碟、終端和網路等)傳輸資料的過程。IO是作業系統的底層功能實現,底層通過I/O指令進行完成。

2.nio簡介

nio是java New IO的簡稱(並不只是指非阻塞IO),在jdk1.4裡提供的新api。Sun官方標榜的特性如下:
–   為所有的原始型別提供(Buffer)快取支援。
–   字符集編碼解碼解決方案。
–   Channel:一個新的原始I/O抽象。
–   支援鎖和記憶體對映檔案的檔案訪問介面。
–   提供多路(non-bloking)非阻塞式的高伸縮性網路I/O。

詳細介紹可見 http://www.iteye.com/topic/834447

3.   非阻塞 IO

何為阻塞、何為非阻塞,非阻塞原理。

何為阻塞?

一個常見的網路IO通訊流程如下:

何為非阻塞?
下面有個隱喻:
一輛從 A 開往 B 的公共汽車上,路上有很多點可能會有人下車。司機不知道哪些點會有哪些人會下車,對於需要下車的人,如何處理更好?
1. 司機過程中定時詢問每個乘客是否到達目的地,若有人說到了,那麼司機停車,乘客下車。 ( 類似阻塞式 )
2. 每個人告訴售票員自己的目的地,然後睡覺,司機只和售票員互動,到了某個點由售票員通知乘客下車。 ( 類似非阻塞 )
很顯然,每個人要到達某個目的地可以認為是一個執行緒,司機可以認為是 CPU 。在阻塞式裡面,每個執行緒需要不斷的輪詢,上下文切換,以達到找到目的地的結果。而在非阻塞方式裡,每個乘客 ( 執行緒 ) 都在睡覺 ( 休眠 ) ,只在真正外部環境準備好了才喚醒,這樣的喚醒肯定不會阻塞。

socket的操作都有一個共同的結構:
1. Read request
2. Decode request
3. Process service
4. Encode reply
5. Send reply
經典的網路服務的設計如下圖,在每個執行緒中完成對資料的處理:


但這種模式在使用者負載增加時,效能將下降非常的快。我們需要重新尋找一個新的方案,保持資料處理的流暢,很顯然,事件觸發機制是最好的解決辦法,當有事件發生時,會觸動handler,然後開始資料的處理。

Reactor模式類似於AWT中的Event處理:


Reactor模式參與者
1.Reactor 負責響應IO事件,一旦發生,廣播發送給相應的Handler去處理,這類似於AWT的thread
2.Handler 是負責非堵塞行為,類似於AWT ActionListeners;同時負責將handlers與event事件繫結,類似於AWT addActionListener

  非阻塞的原理
把整個過程切換成小的任務,通過任務間協作完成。
由一個專門的執行緒來處理所有的 IO 事件,並負責分發
事件驅動機制:事件到的時候觸發,而不是同步的去監視事件。
執行緒通訊:執行緒之間通過 wait,notify 等方式通訊。保證每次上下文切換都是有意義的。減少無謂的程序切換。
Reactor就是上面隱喻的售票員角色。每個執行緒的處理流程大概都是讀取資料、解碼、計算處理、編碼、傳送響應
如圖:


Java的NIO為reactor模式提供了實現的基礎機制,它的Selector當發現某個channel有資料時,會通過SlectorKey來告知我們,在此我們實現事件和handler的繫結。
我們來看看Reactor模式程式碼:

public class Reactor implements Runnable{

  final Selector selector;
  final ServerSocketChannel serverSocket;

  Reactor(int port) throws IOException {
    selector = Selector.open();
    serverSocket = ServerSocketChannel.open();
    InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(),port);
    serverSocket.socket().bind(address);

    serverSocket.configureBlocking(false);
    //向selector註冊該channel
     SelectionKey sk =serverSocket.register(selector,SelectionKey.OP_ACCEPT);

    logger.debug("-->Start serverSocket.register!");

    //利用sk的attache功能繫結Acceptor 如果有事情,觸發Acceptor
    sk.attach(new Acceptor());
    logger.debug("-->attach(new Acceptor()!");
  }


  public void run() { // normally in a new Thread
    try {
    while (!Thread.interrupted())
    {
      selector.select();
      Set selected = selector.selectedKeys();
      Iterator it = selected.iterator();
      //Selector如果發現channel有OP_ACCEPT或READ事件發生,下列遍歷就會進行。
      while (it.hasNext())
        //來一個事件 第一次觸發一個accepter執行緒
        //以後觸發SocketReadHandler
        dispatch((SelectionKey)(it.next()));
        selected.clear();
      }
    }catch (IOException ex) {
        logger.debug("reactor stop!"+ex);
    }
  }

  //執行Acceptor或SocketReadHandler
  void dispatch(SelectionKey k) {
    Runnable r = (Runnable)(k.attachment());
    if (r != null){
      // r.run();

    }
  }

  class Acceptor implements Runnable { // inner
    public void run() {
    try {
      logger.debug("-->ready for accept!");
      SocketChannel c = serverSocket.accept();
      if (c != null)
        //呼叫Handler來處理channel
        new SocketReadHandler(selector, c);
      }
    catch(IOException ex) {
      logger.debug("accept stop!"+ex);
    }
    }
  }
}

以上程式碼中巧妙使用了SocketChannel的attach功能,將Hanlder和可能會發生事件的channel連結在一起,當發生事件時,可以立即觸發相應連結的Handler。

將資料讀出後,可以將這些資料處理執行緒做成一個執行緒池,這樣,資料讀出後,立即扔到執行緒池中,這樣加速處理速度:


可參考:

http://www.jdon.com/concurrent/reactor.htm

http://javag.iteye.com/blog/221641

相關推薦

JAVA 阻塞IO原理

1.  基本概念 IO是主存和外部裝置(硬碟、終端和網路等)傳輸資料的過程。IO是作業系統的底層功能實現,底層通過I/O指令進行完成。 2.nio簡介 nio是java New IO的簡稱(並不只是指非阻塞IO),在jdk1.4裡提供的新api。Sun官方標榜的特性如下:

java阻塞IO(NIO)流程

技術 netty 非阻塞 http cnblogs 分享 nio tty img 單線程 多線程(Netty/Mina) java非阻塞IO(NIO)流程

2.2 Java 阻塞io(NIO)

Java 非阻塞io(NIO) 執行流程 1.Server 開啟通道選擇器Selector 建立ServerSocketChannel通道 並繫結介面 ServerSocketChannel 通道註冊到selector serverSocketCh

Java網絡編程和NIO詳解5:Java 阻塞 IO 和異步 IO

後來 即使 你會 fault 當我 mina 負責 second cti Java網絡編程和NIO詳解5:Java 非阻塞 IO 和異步 IO Java 非阻塞 IO 和異步 IO 轉自https://www.javadoop.com/post/nio-and-aio 本系

Java異步阻塞IO NIO使用與代碼分析

package mes 127.0.0.1 back 之一 write throwable private 建立 [TOC] Java異步非阻塞IO NIO使用與代碼分析 TimeServer程序的NIO實現完整代碼 TimeServer程序來自書本《Netty權威指南》

Java 同步/非同步IO,阻塞/阻塞IO

對於IO,有同步,非同步,阻塞,非阻塞的分類,最近才稍微對這些分類有一些理解,下面記錄一下: 首先,我們需要劃分IO,我們對IO操作分為兩個步驟,1:程式發出IO請求,2:完成實際IO操作,阻塞、非阻塞是針對第一步劃分的,而同步、非同步是針對第二部劃分的。 阻塞/非阻塞:首先,我覺得應該理解

【原創】java-NIO(一)阻塞IO阻塞IO--轉載請註明出處

零、一個小故事 在講解阻塞IO與非阻塞IO之前,先舉出一個小小的例子:        一個老闆經營一個飯店,最初的時候,每來一個客人安排一個服務員招呼,客人很滿意。   後來客人越來越多,需要的服務員越來越多,但是餐廳的後廚已經擠滿了服務員,不

java 同步/非同步IO阻塞/阻塞IO 關係和概念解析

I/O的模型 首先要宣告的一點一定要把同步/非同步 阻塞/非阻塞 以及I/O這三者的概念區別開來,同步大部分是阻塞 的,非同步大部分是非阻塞的,但是它們之間並沒有必然的因果關係 同步與非同步 兩者產生需要有個前提——是否有多個任務或事件發生,只有滿足

同步非同步阻塞阻塞Reactor模式和Proactor模式 (目前JAVA的NIO就屬於同步阻塞IO

在高效能的 I/O 設計中,有兩個比較著名的模式 Reactor 和 Proactor 模式,其中 Reactor 模式用於同步 I/O ,而 Proactor 運用於非同步 I/O 操作。        在比較這兩個模式之前,我們首先的搞明白幾個概念,什麼是阻塞和非阻

Java-NIO(七):阻塞IO阻塞IO

阻塞IO   傳統的 IO 流都是阻塞式的。   也就是說,當一個執行緒呼叫 read() 或 write()時,該執行緒被阻塞,直到有一些資料被讀取或寫入,該執行緒在此期間不能執行其他任務。   因此,在完成網路通訊進行 IO 操作時,由於執行緒會阻塞,所以伺服器端必

【原創】java-NIO(一)阻塞IO阻塞IO

零、一個小故事 在講解阻塞IO與非阻塞IO之前,先舉出一個小小的例子:        一個老闆經營一個飯店,最初的時候,每來一個客人安排一個服務員招呼,客人很滿意。   後來客人越來越多,需要的服務員越來越多,但是餐廳的後廚已經擠滿了服務員,不能請更多的服務員了,之前的

nodejs的異步阻塞IO

nbsp png 使用 nod .com 輪詢 cnblogs 分享 strong 簡單表述一下:發啟向系統IO操作請求,系統使用線程池IO操作,執行完放到事件隊列裏,node主線程輪詢事件隊列,讀取結果與調用回調。所以說node並非真的單線程,還是使用了線程池的多線程。

阻塞IO

tar move try 新建 strip() del connect err close 服務端 from socket import * import time server = socket(AF_INET,SOCK_STREAM) server.bind((‘12

阻塞IO阻塞IO、同步IO、異步IO&&Reactor模式

app sina shu cnblogs 模式 www. htm 同步 ast 3efwzy票僭吩恫越療http://tushu.docin.com/qce8764gnfwar謐浩贅敝客偽http://jz.docin.com/vcqx427mhqxji祭摳嘆頁畔僬http

epoll的水平觸發和邊緣觸發,以及邊緣觸發為什麽要使用阻塞IO

alt 開啟 本機 另一個 trigger stdio.h 什麽 我們 水平 轉自:http://www.cnblogs.com/yuuyuu/p/5103744.html 一.基本概念

IO復用阻塞IO阻塞IO同步IO異步IO

io模型 環境 poll 文件 sig 狀態 nts 一個 大量 轉載:IO復用\阻塞IO\非阻塞IO\同步IO\異步IO 一、 什麽是IO復用? 它是內核提供的一種同時監控多個文件描述符狀態改變的一種能力;例如當進程需要操作多個IO相關描述符時(例如服務器程序要同時查看監

Python37 協程、阻塞IO阻塞IO、同步IO、異步IO

python協成又稱為微線程CPU是無法識別協程的,只能識別是線程,協成是由開發人員自己控制的。協成可以在單線程下實現並發的效果(實際計算還是串行的方式)。 如果使用線程在多個函數之間進行上下文切換,那麽這個上下文的邏輯位置是保存在CPU中的,而協程也有上下文切換的操作,但是協成的上下文邏輯位置不是通過CPU

並發編程 - IO模型 - 1.io模型/2.阻塞io/3.阻塞io/4.多路復用io

post app decode pos win 循環 效率 網絡io als 1.io模型提交任務得方式: 同步:提交完任務,等結果,執行下一個任務 異步:提交完,接著執行,異步 + 回調 異步不等結果,提交完任務,任務執行完後,會自動觸發回調函數同步不等於阻

IO模型之阻塞IO

accept soc apt book nec sets asset python 輪詢 1. IO模型非阻塞 IO Linux下,可以通過設置socket使其變為 non-blocking。當對一個non-blocking socket執行讀操作時,流程是這個樣子:

python-阻塞IO

recv code conn waiting res import client wait bin client端: # import time # import socket # sk = socket.socket(socket.AF_INET,socket.SOCK