NIO 非阻塞IO

Wesley13
• 阅读 606

NIO与IO的区别

NIO 特点:非阻塞,面向缓冲区
IO 特点:阻塞式,面向流

阻塞与非阻塞

java io 是阻塞式的,当一个线程调用read 或者write方法后开始阻塞,直到读取到数据或者写入数据完成,该线程一直处于阻塞状态不能做其他事情。
java nio 通过选择器实现非阻塞式IO,通过一个专门的选择器线程来监视读请写请求是否已经具备完整条件。
非阻塞读:如某个线程发送一个读请求,则它只能获取到当前可用的数据,如果没有可用的数据直接返回,而不是阻塞在这里,直到数据变得可读取。在数据变得可读取之前该线程是可以继续处理其他任务的。
非阻塞写:如某个线程发送写请求,需要写一些数据到通道中,但不需要等到将所有数据都完全写入,该线程可以同时做其他任务。
线程通常将非阻塞的IO的空闲时间用来执行其他通道的IO任务,所以一个单独的线程可以管理多个输入和输出通道。

Channel

通道:channel 是在rt.jar java.util.nio 包下定义的,表示io源与目标打开的链接。
通道不能直接传输数据只能配合缓冲区使用。
通道类似于流 ,但是通道是双向的,即可以将通道指向的目标源数据读入到缓冲区,也可以将缓冲区数据写入到链接通道的目标源。通道好比是铁路,缓冲区为火车,火车载人,通过铁路来运输。

Buffer

缓冲区是存储数据的数组
重要属性
1 capacity:缓冲区容量大小,一旦创建不可改变
2 limit:缓冲区可用数据大小,也就是缓冲区最后一个可操作数据的下标,该下标之后的缓冲区数据不可操作。小于等于capacity
3 position:当前操作的位置。小于等于limit
4 mark:上一次标记的索引位置

Selector

选择器 ,它是Java NIO核心组件中的一个,用于检查一个或多个NIO Channel(通道)的状态是否处于可读、可写。
使用Selector的好处在于: 使用更少的线程来就可以来处理通道了, 相比使用多个线程,避免了线程上下文切换带来的开销。

Selector selector = Selector.open(); 
channel.configureBlocking(false);
SelectionKey key = channel.register(selector, Selectionkey.OP_READ);
channel.configureBlocking(false);

将通道设置为非阻塞式,FileChannel 是阻塞式的不能使用选择器,SocketChannel 网络套接字的通道可以设置为非阻塞式。

register方法的第二个参数是监听事件的类型。选择器可以监听以下四种类型的事件
Connect :链接就 SelectionKey.OP_CONNECT
Accept:接收就绪 SelectionKey.OP_ACCEPT
Read:读就绪 SelectionKey.OP_READ
Write:写就绪 SelectionKey.OP_WRITE

可以通过以下方法来确定以上事件是否准备就绪,它们都会返回一个布尔类型:
链接就绪:selectionKey.isConnectable();
接收就绪:selectionKey.isAcceptable();
读就绪:selectionKey.isReadable();
写就绪:selectionKey.isWritable();

Set selectedKeys =selector.selectedKeys();

Iterator keyIterator = selectedKeys.iterator();

while(keyIterator.hasNext()) {
    SelectionKey key = keyIterator.next();
    if(key.isAcceptable()) {
        // a connection was accepted by a ServerSocketChannel.
    } else if (key.isConnectable()) {
        // a connection was established with a remote server.
    } else if (key.isReadable()) {
        // a channel is ready for reading
    } else if (key.isWritable()) {
        // a channel is ready for writing
    }
    keyIterator.remove();
}

直接缓冲区与非直接缓冲区

非直接缓冲区

客户端向服务端发送数据,先将数据发送到虚拟机中用户地址中空间的缓存中,然后用户地址空间将数据复制到系统内核地址空间的缓存中,内核地址空间将数据写入到系统的物理磁盘中

NIO 非阻塞IO

直接缓冲区

直接缓冲区省去了用户地址空间缓存到内核地址空间缓存的复制过程,用物理内存映射文件来代替,直接将数据存入到物理内存中,然后在将数据存入到物理磁盘中。
可以通过Buffer.allocateDirect 方法来创建直接缓冲区。

NIO 非阻塞IO

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
2年前
IO模型(BIO,NIO,AIO)及其区别
BIO:同步阻塞IONIO:同步非阻塞IOAIO:异步非阻塞IO先弄清楚同步、异步,阻塞、非阻塞概念。io操作分为两部分,发起io请求,和io数据读写。阻塞、非阻塞主要是针对线程发起io请求后,是否立即返回来定义的,立即返回称为非阻塞io,否则称为阻塞io。同步、异步主要针对io数据读写来定义的,读写数据过程中不阻塞线程称为异步io
Wesley13 Wesley13
2年前
JAVA中的BIO、NIO和AIO
Java中的IO方式主要分为3种:BIO(同步阻塞)、NIO(同步非阻塞)和AIO(异步非阻塞)。BIO同步阻塞模式。在JDK1.4以前,使用Java建立网络连接时,只能采用BIO方式,在服务器端启动一个ServerSocket,然后使用accept等待客户端请求,对于每一个请求,使用一个线程来进行处理用户请求。线程的大部分时间都在等待请求的
Wesley13 Wesley13
2年前
Java NIO和IO的区别
IO               NIO面向流           面向缓冲阻塞IO           非阻塞IO无               选择器面向流与面向缓冲JavaNIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。JavaIO面向流意味着每次从流中
Wesley13 Wesley13
2年前
Java.NIO编程一览笔录
Java标准IO与JavaNIO的简单差异示意: Java标准IOJavaNIOAPI调用简单复杂底层实现面向流(stream),单向面向通道(channel),释放CPU、内存压力成效同步阻塞同步非阻塞数据窥视阻塞读取,要么足够,要么没有使用缓冲区(Buffer),读数据时需要检查是否
Wesley13 Wesley13
2年前
Java核心(五)深入理解BIO、NIO、AIO
导读:本文你将获取到:同/异步阻/非阻塞的性能区别;BIO、NIO、AIO的区别;理解和实现NIO操作Socket时的多路复用;同时掌握IO最底层最核心的操作技巧。BIO、NIO、AIO的区别是什么?同/异步、阻/非阻塞的区别是什么?文件读写最优雅的实现方式是什么?NIO如何实现多路复用功能
Wesley13 Wesley13
2年前
NIO阻塞与非阻塞IO
一、使用NIO完成网络通信的三个核心1、通道(Channel):负责连接java.nio.channels.Channel接口|–SelectableChannel|–SocketChannel|–ServerChannel|–DatagramChannel|–Pipe.SinkChannel|–Pipe
Wesley13 Wesley13
2年前
NIO高并发基础
NIO高并发是jdk1.4出现的新的流.NIONewIO同步式非阻塞式IOBIOBlockingIO同步式阻塞式IOUDP/TCPAIOAsynchronousIO异步式非阻塞IOjdk1.8BIO的缺点1.会产生阻塞行为receive/accept/connect/r
Wesley13 Wesley13
2年前
NIO
1、简介1.1Java中的IO介绍1.BIO:BlockingIO,同步式阻塞式IO,即传统的IO,是java中最早期的流2.NIO:NonBlockingIO,又称NewIO,同步式非阻塞IO,是JDK1.4提供的流3.AIO:AsynchronousIO,异步是非阻塞IO,可以认为是NIO的二代版
Wesley13 Wesley13
2年前
NIO非阻塞的IO
!(http://static.oschina.net/uploads/space/2016/0301/173600_GALQ_2336827.jpg)1、TimeClient(客户端)/  @FileName TimeClient.java  @Description:    @Dat
Wesley13 Wesley13
2年前
NIO
一、什么是阻塞和非阻塞?传统的IO流都是阻塞式的。也就是说,当一个线程调用read()或write()时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务。因此,在完成网络通信进行IO操作时,由于线程会阻塞,所以服务器端必须为每个客户端都提供一个独立的线程进行处理,当服务器端