• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

NIO模型和优化点

武飞扬头像
wing12332
帮助1

NIO

一:概述:

NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector(选择器)。传统IO是基于字节流和字符流进行操作(基于流),而NIO基于Channel和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。

二:三者关系

1:一个线程对应一个Selector

2:一个Selector对应多个Channel

3:一个channel对应一个buffer

4:一个buffer是一个内存块(数组)

5:一个channel对应一个客户端连接

6:一个channel绑定一个端口,多个channel可以绑定同一个端口

学新通

三:NIO解决问题/存在问题

1:解决的问题

  1. :一个线程可以接收多个客户端连接

  2. :基于缓存,效率更高(BIO基于流)

  3. :不同的消息分发到不同的channel中

  4. :NIO解决的根本问题就是一个线程多个客户端

2:存在问题

1):若有消息处理太慢,其它channel消息会被卡住,同时其它客户端连接也无法接入。

三:代码演示

下面代码是两个selector,一个是连接selector,一个是读selector

  1.  
    package com.test.io;
  2.  
     
  3.  
    import java.net.InetSocketAddress;
  4.  
    import java.nio.ByteBuffer;
  5.  
    import java.nio.channels.SelectionKey;
  6.  
    import java.nio.channels.Selector;
  7.  
    import java.nio.channels.ServerSocketChannel;
  8.  
    import java.nio.channels.SocketChannel;
  9.  
    import java.util.Iterator;
  10.  
    import java.util.Set;
  11.  
     
  12.  
    public class NIOTest {
  13.  
     
  14.  
    public static void main(String[] args) throws Exception {
  15.  
    //获取一个Selector
  16.  
    Selector selector = Selector.open();
  17.  
    /**
  18.  
    * 创建一个连接类型的通道
  19.  
    * 设置为不阻塞
  20.  
    * 绑定端口6666
  21.  
    * 注册到selector
  22.  
    */
  23.  
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
  24.  
    serverSocketChannel.configureBlocking(false);
  25.  
    serverSocketChannel.bind(new InetSocketAddress(6666));
  26.  
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
  27.  
    while (true){
  28.  
    /**
  29.  
    * 未有连接或消息前阻塞在selector
  30.  
    * 有消息后,继续执行
  31.  
    */
  32.  
    selector.select();
  33.  
     
  34.  
    /**
  35.  
    * 获取消息中的SelectionKey的集合
  36.  
    * 每次有消息过来都会有一个唯一对的SelectionKey添加到Selector中Set集合中
  37.  
    * SelectionKey保存者channel信息
  38.  
    */
  39.  
    Set<SelectionKey> selectionKeys = selector.selectedKeys();//当前所有有消息的事件
  40.  
    Iterator<SelectionKey> it = selectionKeys.iterator();
  41.  
    while (it.hasNext()){//遍历所有消息事件,输出消息
  42.  
    SelectionKey selectionKey = it.next();
  43.  
    //获取到消息事件后,立即移除该消息事件
  44.  
    selectionKeys.remove(selectionKey);
  45.  
    //判断消息事件类型,是连接消息 还是普通消息
  46.  
    if(selectionKey.isValid() && selectionKey.isAcceptable()){//连接消息
  47.  
    /**
  48.  
    * accept是一个阻塞方法,在此处基本不会阻塞,正是因为有消息才到达这里
  49.  
    * 为新的连接生成一个channel
  50.  
    * channel设置为不阻塞
  51.  
    * 注册到selector
  52.  
    */
  53.  
    SocketChannel channel = serverSocketChannel.accept();//与it.hasNext()一个一个地对应,保证channel与SelectionKey对应
  54.  
    channel.configureBlocking(false);
  55.  
    channel.register(selector,SelectionKey.OP_READ);
  56.  
    }
  57.  
    if(selectionKey.isValid() && selectionKey.isReadable()){//普通消息
  58.  
    /**
  59.  
    * 获取消息的通道
  60.  
    */
  61.  
    SocketChannel channel = (SocketChannel) selectionKey.channel();
  62.  
    ByteBuffer byteBuffer = (ByteBuffer) selectionKey.attachment();
  63.  
    channel.read(byteBuffer);
  64.  
    System.out.println("客户端消息:" byteBuffer.toString());
  65.  
    }
  66.  
    }
  67.  
    }
  68.  
    }
  69.  
    }

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhhagiia
系列文章
更多 icon
同类精品
更多 icon
继续加载