[Java]I/O底层原理之三:NIO
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了[Java]I/O底层原理之三:NIO,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2768字,纯文字阅读大概需要4分钟。
内容图文
![[Java]I/O底层原理之三:NIO](/upload/InfoBanner/zyjiaocheng/1046/c589370de9ea4963b9c5e534f740a34a.jpg)
本篇文章参考自并发编程网
NIO 的通道和缓冲区
标准的 IO 是基于字节流和字符流进行操作的,而 NIO 是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区,或从缓冲区写入到通道中。
NIO 是非阻塞 IO
NIO 可以非阻塞的使用 IO,如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情的。当数据被读取到缓冲区后,线程可以继续处理它。从缓冲区写入通道也类似。
NIO 的 Selectors 选择器
选择器用语监听多个通道的事件(如:链接打开、数据达到),单个线程可以坚挺多个数据通道。
一、NIO 的概述
NIO 由以下几个核心组成
- Channels
- Buffers
- Selectors
1 Channel
Channel 有点像流,数据可以从后 Channel 读取到 Buffer 中,也可以从 Buffer 写入到 Channel 中。关于 Channel 有以下几种
- FileChannel
- SocketChannel //通过 TCP 读写网络中的数据
- ServerSocketChannel //监听 TCP 链接,对于每个新进链接都会创建一个 SocketChannel
- DatagramChannel //通过 UDP 读写网络中的数据
1.1 FileChannel
FileChannel 是一个读、写、映射、操作文件的通道。可通过 FileInputStream、FileOutputStream、RandomAccessFile 的 getChannel() 方法获取文件通道的对象,这个文件通道被连接到相同的底层文件。通过 FileInputStream 获取到的文件通道是只读的,通过 FileOutputStream 获取到的文件通道是只写的,另外通过 RandomAccessFile 获取的文件通道可以指定读写方式。
FileChannel 中的部分方法
- read() //可以将数据读取到 Buffer 中,返回有多少字节被读取到。
- write() //传入一个 Buffer ,将其数据写入 FileChannel。
- size() //返回所关联文件大小
- position(long pos) //设置当前读取位置
- truncate() //截取一个文件,指定长度后面的部分将被删除
- force() //将通道中尚未写入磁盘的数据强制写到磁盘上。
- transferTo() //方法可以将数据从 FileChannel 传输到其他 Channel 中。
1.2 SocketChannel
SocketChannel 是一个连接到 TCP 网络套接字的通道。其创建方式有两种:通过调用 open() 方法或者是ServerSocketChannel 获取链接后创建。
我们可以将 configureBlocking(boolean) 方法的值设为 false 使 SocketChannel 成为非阻塞模式,设置之后就可以在异步模式下调用 connect()、read() 和 write() 了。在非阻塞模式下 read() 方法有可能在尚未读取到任何数据时就返回了,所以需要关注它的返回值来确定读取了多少字节。在非阻塞模式下 write() 方法在未写出内容时可能就已经返回,所以需要在循环中调用 write()。
1.3 ServerSocketChannel
ServerSocketChannel 是用来监听 TCP 链接通道的,与 ServerSocket 一样。通过 open() 方法可以创建其对象。通过 accept() 方法来监听新链接。我们可以利用 configureBlocking(boolean) 方法将其设为非阻塞模式,在此模式下 accept() 会立刻返回,如果还没有新链接进来返回的将是 null。
1.4 DatagramChannel
DatagramChannel 是一个能收发 UDP 包的通道。其 receive() 方法会将接收到的数据包内容复制到指定的 Buffer,如果 Buffer 容不下这些数据,多出的数据则会被丢弃。通过 send() 方法可以发送数据。
2 Buffer
Buffer 用于和 NIO 通道进行交互,缓冲区本质上是一块可以写入数据、读取数据的内存。
关于 Buffer 读写数据一般遵循以下四个步骤
- 写入数据到 Buffer
- 调用 flip() 方法
- 从 Buffer 中读取数据
- 调用 clear() 方法或 compact() 方法
当向 Buffer 写入数据时,Buffer 会记录下写了多少数据。一旦要读取数据,需要通过 flip() 方法将 Buffer 从写模式切换到读模式,在读模式下,可以读取之前写入到 Buffer 的数据。
当读取完所有数据后,需要清空缓冲区,让它可以被再次写入。清空缓冲区的方式有两种:调用 clear() 方法或 compact() 方法。clear() 方法会清空整个缓冲区,compact() 方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放置在未读数据后面。
缓冲区本质时一块可以写入数据、读取数据的内存,这块内存被包装成 NIO Buffer 对象,并提供了一组方法,来方便访问该内存。我们来看一下 Buffer 中的三个属性:capacity (缓冲区大小)、position (写数据时的位置)、limit (能读到多少数据)。
关于 Buffer 有以下几种
- ByteBuffer
- MappedByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
3 Scatter/Gather
Scatter/Gather 用于描述从 Channel 中读取或写入的操作。Scatter 是指将 Channel 写入到多个 Buffer,Gather 是指从多个 Buffer 写入到一个 Channel。
4 Selector
Selector 允许单个线程处理多个 Channel。如果应用打开了多个链接(通道),但每个链接的流量都很低,使用 Selector 就会很方便,例如在一个聊天服务器中。
我们通过 Selector.open() 方法可以创建一个 Selector,然后将 Channel 注册到 Selector 上。
原文:http://www.cnblogs.com/tengyunhao/p/7472431.html
内容总结
以上是互联网集市为您收集整理的[Java]I/O底层原理之三:NIO全部内容,希望文章能够帮你解决[Java]I/O底层原理之三:NIO所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。