《Java 源碼分析》:Java NIO 之 SelectionKey__Java

來源:互聯網
上載者:User
《Java 源碼分析》:Java NIO 之 SelectionKey

在ServerSocketChannel源碼分析中我們知道當把一個channel註冊到指定的Selector上時,
實際上就是將(channel,selector)封裝成了一個SelectionKey對象,並將此對象儲存在了Selector對象中。

SelectionKeyImpl k = new SelectionKeyImpl((SelChImpl)ch, this);

在Java NIO 的一些小Demo中,我們常常會看見這樣的代碼:

                // 當註冊事件到達時,方法返回,否則該方法會一直阻塞                 selector.select();                // 獲得selector中選中的相的迭代器,選中的相為註冊的事件                 Set<SelectionKey> set = selector.selectedKeys();                Iterator<SelectionKey> ite = set.iterator();                while(ite.hasNext()){                    SelectionKey selectionKey = (SelectionKey) ite.next();                    // 刪除已選的key 以防重負處理                      ite.remove();                     if(selectionKey.isAcceptable()){//如果有用戶端串連進來                        //先拿到這個SelectionKey裡面的ServerSocketChannel。                        ServerSocketChannel serverSocketChannel = (ServerSocketChannel)selectionKey.channel();                        // do something....                    }                }

今天我們就來看下這個類.

SelectionKeyImpl類中的幾個重要屬性如下:

    final SelChImpl channel;  所擁有的channel對象,該屬性是包私人的    final SelectorImpl selector;   所擁有的selector對象,該屬性是包私人的                       // Index for a pollfd array in Selector that this key is registered with    private int index; //其值表示該SelectionKeyObject Storage Service在與其關聯的Selector對象中所在的位置    private volatile int interestOps; //集合    private int readyOps;

構造方法

    SelectionKeyImpl(SelChImpl ch, SelectorImpl sel) {        channel = ch;        selector = sel;    }

以下是這個類中用來擷取該對象中所關聯的 channel、selector的方法

    public SelectableChannel channel() {        return (SelectableChannel)channel;    }    public Selector selector() {        return selector;    }    int getIndex() {                                    // package-private        return index;    }    void setIndex(int i) {                              // package-private        index = i;    }

都比較簡單,容易理解哈。

在編程中我們使用channel.register(selector,interestSet)方法來將channel註冊到指定的selector中。這個方法的第二個參數。這是一個“interest集合”,意思是在通過Selector監聽此Channel時對什麼事件感興趣。可以監聽四種不同類型的事件:

1、Connect

2、Accept

3、Read

4、Write

通道channel觸發了一個事件的意思是該事件已經就緒。所以,如果某個channel成功串連到另一個伺服器稱為“串連就緒”。如果一個ServerSocketChannel準備好接收新進入的串連稱為“接收就緒”。如果一個有資料可讀的通道可以說是“讀就緒”。等待寫資料的通道可以說是“寫就緒”。

這四種事件用SelectionKey的四個常量來表示,如下:

1、SelectionKey.OP_CONNECT

2、SelectionKey.OP_ACCEPT

3、SelectionKey.OP_READ

4、SelectionKey.OP_WRITE

如果你對不止一種事件感興趣,那麼可以用“位或”操作符將常量串連起來,如下:

int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;

在SelectionKey類的源碼中我們可以看到如下的4中屬性,四個變數用來表示四種不同類型的事件:可讀、可寫、可串連、可接受串連

   public static final int OP_READ = 1 << 0;    public static final int OP_WRITE = 1 << 2;    public static final int OP_CONNECT = 1 << 3;    public static final int OP_ACCEPT = 1 << 4;

SelectionKey類還提供了以下幾個方法用來檢測channel中什麼事件或操作已經就緒

    //測試此通道是否可讀    public final boolean isReadable() {        return (readyOps() & OP_READ) != 0;    }    //測試此通道是否可讀    public final boolean isWritable() {        return (readyOps() & OP_WRITE) != 0;    }    //檢查串連是否完成    public final boolean isConnectable() {        return (readyOps() & OP_CONNECT) != 0;    }    //測試這個SelectionKey對應的通道是否已經接受了一個新的Socket串連。    public final boolean isAcceptable() {        return (readyOps() & OP_ACCEPT) != 0;    }

小結

以上,我們就簡單的看了下SelectionKey類,SelectionKey類簡單來說就是一個輔助類,比較簡單。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.