Selector

前面兩個章節(jié)都描述了Buffer和Channel,那這個章節(jié)就描述NIO三個最核心部分的最后一塊內(nèi)容 - 選擇器(Selector)
  

如何使用

  在前面的章節(jié)中描述過多路復用,一個線程通過選擇器處理和管理多個通道。由此可見,選擇器是用來處理多個通道并監(jiān)聽其通道事件的組件。

  • Create
      只需要調(diào)用 open() 即可創(chuàng)建一個Selector對象:

    Selector selector = Selector.open();
  • Register
      通過 register() 方法注冊通道:

    ServerSocketChannel channel = ServerSocketChannel.open();
    channel.configureBlocking(false);
    SelectionKey selectionKey = channel.register(selector, SelectionKey.OP_ACCEPT);

      在注冊通道之前,把通道設置成非阻塞模式,觀察源碼會發(fā)現(xiàn) register() 會校驗當前通道是否為非阻塞模式,當是阻塞模式時,會拋出IllegalBlockingModeException 異常。在前面一個章節(jié)也提過,為什么FileChannel沒有繼承SelectableChannel,因為它不需要多路復用,所以在使用通道的時候,只有FileChannel不能向選擇器注冊通道,凡是繼承SelectableChannel都能夠向選擇器注冊通道。
      注冊通道方法的第二個參數(shù)是SelectionKey中定義的操作類型,你可以填入任何你感興趣的操作類型,只要這個通道支持,同樣,在執(zhí)行 register() 方法時也會校驗該通道是否能夠支持該操作。
      注冊方法同樣也會返回一個SelectionKey對象。

  • Attach Object
      注冊通道的 register() 方法有一個重載方法,可以向選擇器注冊通道的時候,選擇想要帶上的附加對象:

    public abstract SelectionKey register(Selector sel, int ops, Object att)
        throws ClosedChannelException;

    網(wǎng)友評論