Java NIO - Selector(选择器)

Java NIO - Selector(选择器) 首页 / Nio入门教程 / Java NIO - Selector(选择器)

使用Selector选择器,无涯教程可以使线程知道哪个通道已准备好进入数据写入和读取状态。

可以通过调用其静态方法 open()来获得Selector选择器。打开Selector之后,必须向其注册一个非阻塞通道,该通道返回SelectionKey,SelectionKey可以通过Channel执行的操作。

SelectionKey代表的主要操作或通道状态为-

链接:https://www.learnfk.comhttps://www.learnfk.com/java-nio/java-nio-selector.html

来源:LearnFk无涯教程网

  • SelectionKey.OP_CONNECT   - 准备连接到服务器的通道。

  • SelectionKey.OP_ACCEPT       - 准备接受传入连接的通道。

  • SelectionKey.OP_READ           - 准备读取数据的通道。

  • SelectionKey.OP_WRITE         - 可以进行数据写入的通道。

注册后获得的Selection key具有以下一些重要方法-

  • attach()                   - 此方法用于通过键(key)附加对象(Object),将对象附加到通道的主要目的是识别相同的通道。

  • attachment()          - 此方法用于保留通道中的附加对象。

  • channel()                - 此方法用于获取为其创建特定密钥的通道。

  • selector()                - 此方法用于获取为其创建特定键的选择器。

  • isValid()                  - 此方法返回密钥是否有效。

  • isReadable()           - 此方法返回通道是否可以读取。

  • isWritable()            - 此方法返回通道是否可以写。

  • isAcceptable()        - 此方法返回气密钥的通道是否已准备好接受传入的连接。

  • isConnectable()     - 此方法判断通道是否已完成其Socket连接操作。

  • isAcceptable()        - 此方法判断通道是否已准备好接受新的Socket连接。

  • interestOps()          - 此方法检索此密钥的interset集合。

  • readyOps()              - 此方法检索就绪集合。

可以通过调用其静态方法 select()从selector中选择一个通道。selector的select方法重载为-

  • select()                        - 此方法阻塞当前线程,直到至少一个通道准备好为止。

  • select(long timeout) - 此方法与select()相同,它在最大超时毫秒内阻塞线程。

  • selectNow()                - 此方法完全不会阻塞,无论通道准备就绪,它都会立即返回。

同样,为了留下阻塞的线程来调用select方法,可以从选择器中调用 wakeup()方法,然后在select()内部等待的线程将立即返回。

最后,可以通过调用 close()方法来关闭选择器,该方法还将使在此Selector中注册的所有SelectionKey无效,同时关闭Selector选择器。

Selector示例

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class SelectorDemo {
   public static void main(String[] args) throws IOException {
      String demo_text = "This is a demo String";	
      Selector selector = Selector.open();
      ServerSocketChannel serverSocket = ServerSocketChannel.open();
      serverSocket.bind(new InetSocketAddress("localhost", 5454));
      serverSocket.configureBlocking(false);
      serverSocket.register(selector, SelectionKey.OP_ACCEPT);
      ByteBuffer buffer = ByteBuffer.allocate(256);
      while (true) {
         selector.select();
         Set<SelectionKey> selectedKeys = selector.selectedKeys();
         Iterator<SelectionKey> iter = selectedKeys.iterator();
         while (iter.hasNext()) {
            SelectionKey key = iter.next();
            int interestOps = key.interestOps();
            System.out.println(interestOps);
            if (key.isAcceptable()) {
               SocketChannel client = serverSocket.accept();
               client.configureBlocking(false);
               client.register(selector, SelectionKey.OP_READ);
            }
            if (key.isReadable()) {
               SocketChannel client = (SocketChannel) key.channel();
               client.read(buffer);
               if (new String(buffer.array()).trim().equals(demo_text)) {
                  client.close();
                  System.out.println("Not accepting client messages anymore");
               }
               buffer.flip();
               client.write(buffer);
               buffer.clear();
            }
            iter.remove();
         }
      }
   }
}

祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)

技术教程推荐

深入浅出gRPC -〔李林锋〕

趣谈Linux操作系统 -〔刘超〕

Swift核心技术与实战 -〔张杰〕

罗剑锋的C++实战笔记 -〔罗剑锋〕

Selenium自动化测试实战 -〔郭宏志〕

Spark性能调优实战 -〔吴磊〕

中间件核心技术与实战 -〔丁威〕

快手 · 音视频技术入门课 -〔刘歧〕

结构执行力 -〔李忠秋〕

好记忆不如烂笔头。留下您的足迹吧 :)