Java NIO核心組件-Selector和Channel

昨天我們介紹了一下SelectorProviderIO multiplexing.特別是IO multiplexing中的epoll系統(tǒng)調(diào)用,是Linux版本的Java的NIO的核心實現(xiàn).

那今天我們就來介紹一下, Java NIO中的核心組件, Selector和Channel.這兩個組件,對于熟悉Java OIO,而不熟悉Java NIO的朋友來說,理解其作用是極其不易的.

前提條件

在閱讀這篇文章之前,如果各位不熟悉甚至沒有聽說過IO multiplexing中的epoll,請務必花時間去了解一下.了解了它們之后,就很容易理解Java NIO的實現(xiàn)了.

這里我們講解的是Linux版本且內(nèi)核版本大于2.6的Java NIO的實現(xiàn),對于其他的系統(tǒng)或者內(nèi)核版本較低的Java NIO,其具體實現(xiàn)是不一樣的.

舉例來說, Linux 內(nèi)核版本大于等于2.6的Java NIO是采用epoll來實現(xiàn)的.而Linux內(nèi)核版本小于2.6的Java NIO,則是采用poll來實現(xiàn)的.

Selector和Channel

SelectorChannel的關系,如下圖所示:

各位如果了解過epoll的話,應該知道epoll_create操作會創(chuàng)建一個需要被監(jiān)聽的file descriptor.然后,epoll_ctl操作會為告訴內(nèi)核,需要監(jiān)聽一個file descripitor的什么事件.最后,使用epoll_wait來告訴內(nèi)核開始監(jiān)聽.

這里我們就可以把Selector比作epoll中的內(nèi)核.把Channel比作epoll_create操作創(chuàng)建的file descriptor.這樣就很容易理解了吧.

因為Java NIO實際上是給我們對IO multiplexing進行了封裝,隱藏了其底層的實現(xiàn).所以我們完全可以這樣來理解.

貼出在Java NIO tutorial中看到的一個圖片,

對于這張圖片,我實在是不能茍同其說法.我們可以看到,在這張圖片中,我們可以看到,一個線程中只有一個Selector,每個Selector負責監(jiān)控三個Channel.而實際上,一個線程中,并不是必須只能有一個Selector.一個Selector也不是只能注冊三個Channel.

AbstractSelector的源碼中,我們可以看到,實際上它只維護了一個不再監(jiān)聽的Channel的集合:

我們查看具體的Selector的父類,SelectorImpl,中的register方法的實現(xiàn).跟具體的Selector實現(xiàn)相關的類,在JDK提供的src.zip源碼包中是找不到的.這里使用CFR反編譯器反編譯rt.jar包.從中找到其實現(xiàn).

我們可以看到,它會把Channel進一步封裝成SelectionKeyImpl.然后使用implRegister方法來實現(xiàn)具體的注冊過程.從SelectorImpl的源碼中,我們同樣可以看到,implRegister方法是一個抽象方法,需要其子類來實現(xiàn)具體的注冊過程.

這里我們感興趣的子類是EPollSelectorImpl,我們查看其源碼,可以看到其中維護了一個從file descriptorSelectionKeyImpl的Map.我們剛剛也提到了,SelectionKeyImpl中,包裝了一個Channel,

我們從EPollSelectorImplimplRegister方法中,也沒有看到會對Map<Integer, SelectionKeyImpl>這個表示EPollSelectorImpl維護的Channel的Map進行尺寸限制的操作.即并沒有限制一個EPollSelectorImpl可以注冊的Channel的數(shù)量.

反而是在Channel中,維護了它向Selector注冊時,Selector給其返回的SelectionKey的集合.相當于維護了它已經(jīng)注冊的Selector的集合.

我們查看AbstractSelectableChannel的向Selector注冊的源碼:

我們可以看到,它會把Selector給它返回的SelectionKey加入到上面我們說過的那個集合中,我們看看addKey()方法的具體實現(xiàn):

在這里我們就可以看到,默認情況下,Channel會創(chuàng)建一個容量為3的表示它注冊的Selector的集合.當它需要向更多的Selector注冊時,則對這個集合進行擴容.

而并沒有提到一個Selector中最多可以注冊多少個Channel.

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 這兩天了解了一下關于NIO方面的知識,網(wǎng)上關于這一塊的介紹只是介紹了一下基本用法,沒有系統(tǒng)的解釋NIO與阻塞、非阻...
    Ruheng閱讀 7,254評論 5 48
  • 概述 Selector是NIO中實現(xiàn)I/O多路復用的關鍵類。Selector實現(xiàn)了通過一個線程管理多個Channe...
    tomas家的小撥浪鼓閱讀 5,463評論 6 26
  • Java NIO(New IO)是從Java 1.4版本開始引入的一個新的IO API,可以替代標準的Java I...
    JackChen1024閱讀 7,964評論 1 143
  • 作者: 一字馬胡 轉(zhuǎn)載標志 【2017-11-24】 更新日志 一、Java OIO Java OIO (Jav...
    一字馬胡閱讀 1,458評論 0 12
  • 最近特別著迷Eason的陰天快樂。一遍一遍重復著,絲毫沒有感覺厭煩,反而越來越喜歡。 我從小就不喜歡陰天,總覺得陰...
    藍格里西瓜閱讀 519評論 0 2

友情鏈接更多精彩內(nèi)容