📜  Java NIO-选择器(1)

📅  最后修改于: 2023-12-03 15:15:57.343000             🧑  作者: Mango

Java NIO-选择器

选择器(Selector)是Java NIO中对非阻塞网络通信的核心支持。Selector可以检测多个注册的通道上是否有事件发生(数据到达、连接打开等),并能够实现单线程管理多个通道,即可以轮询多个Channel获取数据,从而实现了非阻塞式IO。

选择器使用步骤如下:

  1. 创建Selector
  2. 绑定Channel到Selector
  3. 注册SelectionKey到Selector上
  4. 选择器开始轮询
创建Selector

使用Selector.open()方法创建新的选择器(Selector):

Selector selector = Selector.open();
绑定Channel到Selector

要使用选择器监控通道,需要先将通道绑定到选择器上。这可以通过SelectableChannel.register()方法完成,如下:

SelectableChannel channel = ...
channel.configureBlocking(false);
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
注册SelectionKey到Selector上

要在选择器上注册一个通道,我们可以使用SelectableChannel.register()方法。在注册时指定我们想要监听的事件类型,例如OP_READ等:

SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
选择器开始轮询

要使用选择器来处理通道事件,我们需要不断的轮询选择器。可以使用Selector.select()方法。这个方法会阻塞,直到至少有一个事件发生。一旦事件发生,select()方法将返回已经准备就绪的SelectionKey实例。可以使用SelectionKey的readyOps()方法来确定哪些事件已经就绪。

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.isReadable()) {
            // 处理读事件
        } else if (key.isWritable()) {
            // 处理写事件
        }

        keyIterator.remove();
    }
}

使用选择器可以大大提高IO效率,避免线程阻塞,提高程序吞吐量。使用选择器时需要注意多线程同步问题,因为Selector本身不是线程安全的。

参考文献: https://www.baeldung.com/java-nio-selector