Java非阻塞I/O模型之NIO相关知识总结

组件说明

(1)Channel:NIO模型中的管道,管道是链接建立和通信的重要组件,我们可以理解管道是一个容器环境,我们所有的I/O的建立读取都可以在这个容器中进行

(2)Selector:NIO中的选择器,NIO是由事件驱动的,当有链接事件或者读取事件发生时,这个事件可以注册到这个选择器上,并且最终被我们检测到。

(3)SelectionKey:我们可以在Selector中进行检测是否有SelectionKey产生,并且根据这个SelectionKey中的信息判断时什么事件发生了。

代码说明

(1)开启ServerSocketChannel,并开始监听

//初始化一个网络地址,并绑定7000端口号
InetSocketAddress inetSocketAddress = new InetSocketAddress(7000);
//ServerSocketChannel.open() 方法实例化一个ServerSocketChannel对象
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//serverSocketChannel绑定初始化的网络地址,并开始监听
serverSocketChannel.socket().bind(inetSocketAddress);
//将这个通道设置为非阻塞的
serverSocketChannel.configureBlocking(false);

(2)初始化选择器,并将这个选择器注册到上面的网络通道中

//得到一个Selector对象
Selector selector = Selector.open();
//在channel上注册selector,并且告诉这个选择器初始应该监听的事件,
//SelectionKey.OP_ACCEPT 为监听链接进入的事件,初始化并不监听数据读取的事件
//SelectionKey.OP_READ 事件读取事件,需要在有链接进入时,配合链接一起注册
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

(3)主循环

//循环等待客户端链接
while(true){
     //等待1秒,1秒内没有链接事件发生,直接返回
     if(selector.select(1000)==0){
         System.out.println("服务器等待了1秒,无连接进入");
         continue;
      }
      //有事件发生,拿到集合
      //selector.selectedKeys() 关注事件的集合
      //通过这个可以反向获取通道
      Set<SelectionKey> selectionKeys = selector.selectedKeys();

      //遍历集合,使用迭代器
      Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
      while(keyIterator.hasNext()){
           //获取事件key
           SelectionKey key = keyIterator.next();
           //根据key对应的通道发生的事件做相应的处理
           if(key.isAcceptable()){
               //如果是ACCEPT事件,客户端链接
               //传统的accept()是阻塞的,但是在NIO中,当key.isAcceptable()方法返回true的时候,这个链接就已经存在了,所以accept()会立刻执行
               SocketChannel socketChannel = serverSocketChannel.accept();
               socketChannel.configureBlocking(false);
               //将当前的socketChannel注册的selector,关注事件为READ,同时给Channel关联一个Buffer
               SelectionKey register = socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(128));

           }else if(key.isReadable()){
               //发生了READ事件
               //通过key反向获取Channel
               SocketChannel channel = (SocketChannel)key.channel();
               //获取到该channel关联的buffer
               ByteBuffer buffer =(ByteBuffer) key.attachment();
               channel.read(buffer);
               System.out.println("From 客户端 :"+new String(buffer.array()));

           }

           //手动在集合中移除当前的SelectionKey否则可能会出现重复操作
           keyIterator.remove();

       }

}

总结

(1)使用一个事件驱动的方式,在没有事件发生的时候,服务器可以去做一些自己需要做的事。

(2)当有事件发生的时候,通过Selector去关心是什么事件。

(3)甚至不需要使用多线程,就能同时处理更多的链接请求。

(4)当然我们也可以配合多线程,来更有效的利用服务器资源,满足需求更复杂,请求更多的场景。

(5)NIO是Netty的基础,读者可以多手动编写一下NIO的实现,来更深的了解Netty。

到此这篇关于Java非阻塞I/O模型之NIO相关知识总结的文章就介绍到这了,更多相关Java NIO内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java中BIO、NIO、AIO都有啥区别

    一.BIO(Blocking IO,也被称作old IO) 同步阻塞模型,一个客户端连接对应一个处理线程 对于每一个新的网络连接都会分配给一个线程,每隔线程都独立处理自己负责的输入和输出, 也被称为Connection Per Thread模式 缺点: 1.IO代码里read操作是阻塞操作,如果连接不做数据读写操作会导致线程阻塞,浪费资源 2.如果线程很多,会导致服务器线程太多,压力太大,比如C10K问题 所谓c10k问题,指的是服务器同时支持成千上万个客户端的问题,也就是concurrent

  • Java实现基于NIO的多线程Web服务器实例

    代码地址:https://github.com/iyuanyb/webserver 实现了 静态.动态资源获取: Cookie.Session.HTTP 长连接,及 Session 和 HTTP 长连接的定时清除: 类似 Spring MVC 的注解式编程,如 @RequestMapping @RequestParam 等,方法中可以根据参数名从前台获取数据,可以传递对象,也支持级联属性,如: // GET /page?pageSize=10&pageNum=1 HTTP/1.1 @Reques

  • 基于Java写minio客户端实现上传下载文件

    前言: 确保已经安装了minio的服务端 代码: pom.xml <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>7.0.2</version> </dependency> application.yml server: port:90 minio: url: http://10.69.94.140

  • 详解java NIO之Channel(通道)

    通道(Channel)是java.nio的第二个主要创新.它们既不是一个扩展也不是一项增强,而是全新.极好的Java I/O示例,提供与I/O服务的直接连接.Channel用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效地传输数据. channel介绍 通道是访问I/O服务的导管.I/O可以分为广义的两大类别:File I/O和Stream I/O.那么相应地有两种类型的通道也就不足为怪了,它们是文件(file)通道和套接字(socket)通道.我们看到在api里有一个F

  • 深入了解java NIO之Selector(选择器)

    这一节我们将探索选择器(selectors).选择器提供选择执行已经就绪的任务的能力,这使得多元 I/O 成为可能.就像在第一章中描述的那样,就绪选择和多元执行使得单线程能够有效率地同时管理多个 I/O 通道(channels).C/C++代码的工具箱中,许多年前就已经有 select()和 poll()这两个POSIX(可移植性操作系统接口)系统调用可供使用了.许过操作系统也提供相似的功能,但对Java 程序员来说,就绪选择功能直到 JDK 1.4 才成为可行的方案. 下面我们来使用选择器:

  • java基于netty NIO的简单聊天室的实现

    一.为何要使用netty开发 由于之前已经用Java中的socket写过一版简单的聊天室,这里就不再对聊天室的具体架构进行细致的介绍了,主要关注于使用netty框架重构后带来的改变.对聊天室不了解的同学可以先看下我的博客(<JAVA简单聊天室的实现>) 本篇博客所使用的netty版本为4.1.36,完整工程已上传到Github(https://github.com/Alexlingl/Chatroom),其中lib文件夹下有相应的netty jar包和source包,自行导入即可. 1.为何要

  • Java NIO异步文件通道原理及用法解析

    在Java 7,AsynchronousFileChannel 被添加到了Java NIO中.使用AsynchronousFileChannel可以实现异步地读取和写入文件数据. 创建一个AsynchronousFileChannel 我们可以使用AsynchronousFileChannel提供的静态方法 open() 创建它.示例代码如下: Path path = Paths.get("data/test.xml"); AsynchronousFileChannel fileCha

  • Java实现NIO聊天室的示例代码(群聊+私聊)

    功能介绍 功能:群聊+私发+上线提醒+下线提醒+查询在线用户 文件 Utils 需要用maven导入下面两个包 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> </dependency> <dependency> <group

  • 详细了解JAVA NIO之Buffer(缓冲区)

    当我们需要与 NIO Channel 进行交互时, 我们就需要使用到 NIO Buffer, 即数据从 Buffer读取到 Channel 中, 并且从 Channel 中写入到 Buffer 中.缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存. 缓冲区基础 Buffer 类型有: 缓冲区是包在一个对象内的基础数据的数组,Buffer类相比一般简单数组而言其优点是将数据的内容和相关信息放在一个对象里面

  • Java NIO Selector用法详解【含多人聊天室实例】

    本文实例讲述了Java NIO Selector用法.分享给大家供大家参考,具体如下: 一.Java NIO 的核心组件 Java NIO的核心组件包括:Channel(通道),Buffer(缓冲区),Selector(选择器),其中Channel和Buffer比较好理解 简单来说 NIO是面向通道和缓冲区的,意思就是:数据总是从通道中读到buffer缓冲区内,或者从buffer写入到通道中. 关于Channel 和 Buffer的详细讲解请看:Java NIO 教程 二.Java NIO Se

  • 使用java NIO及高速缓冲区写入文件过程解析

    这篇文章主要介绍了使用java NIO及高速缓冲区写入文件过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 代码如下 byte[] bytes = Files.readAllBytes(Paths.get("E:\\pdf\\aaa\\html\\text.txt").normalize()); String text = IOUtils.toString(bytes); String xml = text.substring(

随机推荐