天天看點

epoll nio差別_NIO-非阻塞的IO

上一篇介紹了BIO,我們知道,阻塞的根本原因是核心系統中處理方法是阻塞的

一.NIO相對于BIO來說,是新IO,或者非阻塞IO,是核心系統更新後産物

epoll nio差別_NIO-非阻塞的IO

上面代碼我們看到,serverSocketChannel.accept()設定成非阻塞後,如果沒有用戶端連接配接,代碼會不停地死循環運作。同理,socketChannel.configureBlocking(false); socketChannel.read方法和socketChannel.write方法也是非阻塞的,有需要讀寫的資料,直接讀寫,沒有的話代碼直接往下執行,空循環,然後再進行下一次循環看看有沒有要讀寫的資料。

有沒有發現一個問題,一旦代碼不阻塞了,方法accept、read、write等就要放在循環體中,條件不滿足時,隻能不停的空輪循。這種方式顯然不好,怎麼解決呢?可不可以統一交給一個對象來處理,讓它來負責監控對象serverSocketChannel、socketChannel中有沒有需要處理的事情

二.select和poll

(1)select==>時間複雜度O(n)

select()的機制中提供一種fd_set的資料結構,long類型的數組,每一個數組元素都能與已打開的檔案句柄(不管是Socket句柄,還是其他檔案或命名管道或裝置句柄)建立聯系,當調用select()時,由核心根據IO狀态修改fd_set的内容,由此來通知執行了select()的程序哪一Socket或檔案可讀,無差别輪詢所有句柄,找出需要處理的,對他們進行操作。select無差别輪詢複雜度,同時處理的流越多,無差别輪詢時間就越長

(2)poll==>時間複雜度O(n)

poll本質上和select沒有差別,管理多個描述符也是進行輪詢, 但是它沒有最大連接配接數的限制,基于連結清單來存儲的

三.epoll和多路複用器

epoll可以了解為event poll,epoll會把哪個流發生了怎樣的I/O事件通知我們,複雜度降低到了O(1),不再是盲目的輪循所有打開的流

不知道大家有沒有想到監聽器,将一堆觀察者、被觀察者注冊到廣播器上面,當被觀察者有事件發生時,利用廣播器通知特定的觀察者,epoll類似于觀察者模式

select,poll,epoll都是IO多路複用的機制,I/O多路複用就通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。多路複用,說白了,就是指一個對象可以反複監控着多個鍊路通道流上面的事件情況,selector

四.byteBuffer

緩沖區(Buffer)就是在記憶體中(堆内或堆外)預留指定大小的存儲空間用來對輸入/輸出(I/O)的資料作臨時存儲資料的緩沖區,好處:

1、減少實際的實體讀寫次數

2、緩沖區在建立時就被配置設定記憶體,這塊記憶體區域一直被重用,可以減少動态配置設定和回收記憶體的次數

緩沖區直接為通道(Channel)服務,寫入資料到通道或從通道讀取資料,面向可讀可寫的緩沖區而不是位元組流,大大提高傳遞的效率,底層本質上是一個數組結構