NIO中selector的概念

有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top

全网最细面试题手册,支持艾宾浩斯记忆法。这是一份最全面、最详细、最高质量的 java面试题,不建议你死记硬背,只要每天复习一遍,有个大概印象就行了。 https://store.amazingmemo.com/chapterDetail/1685324709017001`

NIO中的Selector概念

在Java NIO中,Selector是一个高级工具,它可以检测一个或多个NIO通道(Channel),并能够知晓通道是否为诸如读取、写入等操作做好准备。这种机制使得单个线程可以管理多个通道,因此也可以管理多个网络连接。

为什么使用Selector?

在传统的IO模型中,每个连接创建时都需要一个线程去处理,当并发的连接数增加时,线程数也会线性增加,这会带来线程上下文切换和资源消耗的问题。而使用Selector能够通过一个线程来处理多个通道,极大地减少了资源的消耗,提高了程序的效率。

Selector的工作原理

Selector内部使用了一种叫做多路复用的技术。在这种模式下,Selector会询问每个注册的通道是否有事件准备就绪。如果有,它会集中处理这些事件,这样就可以只用一个单独的线程来管理多个通道的事件。

如何使用Selector

以下是使用Selector的基本步骤:

  1. 打开Selector

    Selector selector = Selector.open();
  2. 向Selector注册通道 首先,通道必须设置为非阻塞模式,因为阻塞模式的通道不能与Selector一起使用。然后,通道可以注册到Selector上:

    channel.configureBlocking(false);
    SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
  3. 选择就绪的通道

    while(true) {
      int readyChannels = selector.select();
      if(readyChannels == 0) continue;
      Set<SelectionKey> selectedKeys = selector.selectedKeys();
      Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
      while(keyIterator.hasNext()) {
        SelectionKey key = keyIterator.next();
        if(key.isAcceptable()) {
          // a connection was accepted by a ServerSocketChannel.
        } else if (key.isConnectable()) {
          // a connection was established with a remote server.
        } else if (key.isReadable()) {
          // a channel is ready for reading
        } else if (key.isWritable()) {
          // a channel is ready for writing
        }
        keyIterator.remove();
      }
    }

在这个循环中,selector.select()是一个阻塞调用,只有至少有一个通道就绪时才会返回。selectedKeys集合包含了所有就绪的通道的SelectionKey,然后通过迭代器可以遍历这些键,检查通道就绪的事件类型,并相应地进行处理。

总结

Selector是Java NIO中的核心组件之一,它允许单线程有效地管理多个通道,从而处理多个网络连接。这种模型在需要处理成千上万个连接的高性能网络服务器中非常有用。正确使用Selector可以使应用程序更加高效,响应更快,且更加可扩展。

最后更新于