栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java IO模型之 NIO

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java IO模型之 NIO

目录

1.简介:

2.Buffer基本介绍:

3.通道(channel)基本介绍:

4.Selector(选择器)介绍:


1.简介:

NIO是指同步非阻塞,是对BIO(同步阻塞)的改进,它的代码在java.nio及其子包下。

NIO关键的三要素是:Buffer(缓冲区)、Channel(通道)、Selector(选择器)。

以常用的网络TCP通信为例(ServerSockerChannel与SockerChannel),客户端和服务端的线程都不会被阻塞:

  1. 客户端(通过Buffer):Client不直接通过通道进行通信,而是在client与通道之间加了Buffer缓冲区(IntBufer、ByteBuffer......,除了boolean类型,别的都提供了对应的buffer,便于根据需要选择对应的Buffer),由Buffer与通道进行数据交互,这样将client解放出来,只有当缓冲区数据准备好的时候(发送数据或者接收数据,准备好),client才会进行处理,如果数据没有准备好,则线程可以去做别的,而不是阻塞在这里。
  2. 服务端(通过selector和Buffer):服务端一个线程通过selector选择器,可以处理多个请求(channel), 多个channel通过事件的方式将自己注册到一个selector,采用的是事件驱动的机制,selector监听多个通道的事件,哪个通道发生了某个事件,seletor会选择它,然后线程会去处理(还是通过Buffer与Channel进行通信),当然线程不会阻塞在某个channel上(非阻塞还是通过Buffer实现的)。如果所有通道都没有事件发生,那么线程则都不会去处理,线程会去做别的事情,而不是阻塞在这里等待某个通道发生事件。

 java NIO基本介绍, 一共7条:

NIO与BIO的比较:

2.Buffer基本介绍:

Buffer缓冲区(IntBufer、ByteBuffer......,除了boolean类型,别的都提供了对应的buffer,便于根据需要选择对应的Buffer),此外还有MappedByteBuffer(直接在内存中修改文件内容,修改可以自动映射到文件),Buffer数组等。

下面的例子讲述了怎样使用IntBuffer:  其中的关键点包括flip()操作和clean()操作,flip操作将Buffer数组的指针position的值赋值给limit,然后position变为0,这样就可以从0到limit读取Buffer数组中的数据了。

3.通道(channel)基本介绍:

 FileChannel的buffer和channel都是在客户端,并且Filechannel是从流中获取的。

关于Buffer和channel的注意事项

4.Selector(选择器)介绍:

 

5.NIO非阻塞编程整体流程分析:

下面给出尽量详细的描述(网络TCP通信):

  1. 新建一个ServerSocketChannel,为其设置监听端口,然后设置为非阻塞。新建一个Selector,将ServerSocketChannel注册到该Selector。
  2. 调用selector的select(......)方法(例如select(1000), 停顿1秒钟),查看ServerSocketChannel有没有事件发生,如果没有事件发生(select(......)返回0),则继续select(......),看看有没有事件发生,当然了,线程也可以去干别的,不会阻塞等待事件发生。
  3. 如果如果有事件发生(select(......)返回值大于0),通过selector.selectedKeys()得到事件的集合Set,得到这个集合的迭代器Iterator,用迭代器遍历事件集合(SelectionKey key = keyIterator.next()),根据每个事件的类型(例如读,新的客户端连接)进行处理。
  4. 如果是新的客户端连接(key.isAcceptable()),则得到一个新的SockerChannel(SocketChannel socketchannel = serverSockertChannel.accept(), 不会阻塞,因为这里根本不需要等待,直接就是一个新的客户端连接),然后将得到的SocketChannel注册到Selector中(通过register(Selector, int ops, Buffer)方法,其中Selector是要注册到的selector,ops是要注册的操作,比如读、写、已连接、准备连接,如果客户端建立连接后,要发送数据,那么我们这里选择读事件SelectionKey.OP_READ),Buffer是缓冲区,channel必须要关联一个Buffer,在Selector中被以SelectionKey对象的集合的方式存储,一个SelectionKey对应一个SocketChannel。注册方法register(Selector, int ops)的返回值是一个SelectionKey;
  5. 如果是读事件(客户端发送数据过来, (key.isReadable())),通过key反向获取到SocketChannel(key.isAcceptable()的时候,注册到了selector),得到注册的buffer,然后socketChannel.read(buffer)将数据读取到buffer中,这样就得到了客户端的数据(new String(buffer.array()))。
  6. 新来多少个客户端请求,就生成和注册多少个SocketChannel。每次Selector通过select()方法(select()方法本身是阻塞的,但是其有多个重载方法,可以指定方法执行时间,可以遍历一次直接返回等)得到有多少个SocketChannel发生了事件。如果是已经注册的SocketChannel发生了事件(例如可读事件),会将发生事件的SelectionKey放到另外一个集合中,线程遍历这个发生事件的SelectionKey集合,进行处理,可以通过SelectionKey的channel()方法反向获取到SocketChannel,通过得到的SockerChannel,完成业务处理

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/352352.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号