Selector

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

如何使用

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

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

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

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

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

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

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

    網(wǎng)友評論