zoukankan      html  css  js  c++  java
  • Java NIO (四) 选择器(Selector)

    选择器(Selector) 是 SelectableChannle 对象的多路复用器,Selector 可以同时监控多个 SelectableChannel 的 IO 状况,也就是说,利用 Selector可使一个单独的线程管理多个 Channel,selector 是非阻塞 IO 的核心。

    SelectableChannle 的继承树如下图:

    选择器(Selector)的应用:

    当通道使用register(Selector sel, int ops)方法将通道注册选择器时,选择器对通道事件进行监听,通过第二个参数指定监听的事件类型。

    其中可监听的事件类型包括以下:

      读 : SelectionKey.OP_READ (1)

      写 : SelectionKey.OP_WRITE (4)

      连接 : SelectionKey.OP_CONNECT (8)

      接收 : SelectionKey.OP_ACCEPT (16)

    如果需要监听多个事件是:

      int key = SelectionKey.OP_READ | SelectionKey.OP_WRITE ; //表示同时监听读写操作

    如何应用请看代码:

    public class NIOBlocking2 {
    
       //客户端 @Test
    public void client() throws Exception { //1. 获取socketChannel SocketChannel sChannel = SocketChannel.open(); //2. 创建连接 sChannel.connect(new InetSocketAddress("127.0.0.1", 9898)); ByteBuffer buf = ByteBuffer.allocate(1024); //3. 设置通道为非阻塞 sChannel.configureBlocking(false); @SuppressWarnings("resource") Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { String msg = scanner.nextLine(); buf.put((new Date() + ":" + msg).getBytes()); buf.flip(); //4. 向通道写数据 sChannel.write(buf); buf.clear(); } }
       //服务端 @Test
    public void server() throws Exception { //1. 获取服务端通道 ServerSocketChannel ssChannel = ServerSocketChannel.open(); ssChannel.bind(new InetSocketAddress(9898)); //2. 设置为非阻塞模式 ssChannel.configureBlocking(false); //3. 打开一个监听器 Selector selector = Selector.open(); //4. 向监听器注册接收事件 ssChannel.register(selector, SelectionKey.OP_ACCEPT); while (selector.select() > 0) { //5. 获取监听器上所有的监听事件值 Iterator<SelectionKey> it = selector.selectedKeys().iterator(); //6. 如果有值 while (it.hasNext()) { //7. 取到SelectionKey SelectionKey key = it.next(); //8. 根据key值判断对应的事件 if (key.isAcceptable()) { //9. 接入处理 SocketChannel socketChannel = ssChannel.accept(); socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { //10. 可读事件处理 SocketChannel channel = (SocketChannel) key.channel(); readMsg(channel); } //11. 移除当前key it.remove(); } } } private void readMsg(SocketChannel channel) throws IOException { ByteBuffer buf = ByteBuffer.allocate(1024); int len = 0; while ((len = channel.read(buf)) > 0) { buf.flip(); byte[] bytes = new byte[1024]; buf.get(bytes, 0, len); System.out.println(new String(bytes, 0, len)); } } }

    NIO的非阻塞性:

    nio的非阻塞是对于网络通道来说的,需要使用Channel.configureBlocking(false)来设置通道为非阻塞的,如果没设置,默认是阻塞的。

  • 相关阅读:
    浅拷贝与深拷贝
    Hibernate入门(1)-第一个Hibernate程序
    Spring入门(10)-Spring JDBC
    【Java,IDEA】创建自己的代码模版快速生成
    【Java,IDEA】使用IDEA自动生成序列化ID
    【Project】原生JavaWeb工程 02 登陆业务的流程(第一阶段样例)
    【AJAX】Asynchronous JavaScript And XML (非同步的JS & XML)
    【JS】06 语法补充
    【JS】05 DOM 文档对象模型 P2 元素的CRUD、Dom集合对象
    【JS】04 DOM 文档对象模型 P1 查找元素、改变内容、绑定事件
  • 原文地址:https://www.cnblogs.com/qq-361807535/p/6670529.html
Copyright © 2011-2022 走看看