基于NIO的同步非阻塞式编程

Java NIO(Non-blocking Input/Output)提供了不同于传统IO的编程模型,主要特点是引入了Buffer、Channel和Selector。Buffer用于数据的读写,Channel是数据传输的通道,Selector则允许单线程处理多个Channel,提高了效率。NIO的核心在于非阻塞的IO操作,使得程序在等待数据准备就绪时不会被阻塞,提升了系统性能。
摘要由CSDN通过智能技术生成

IO(BIO)和NIO的区别:其本质就是阻塞和非阻塞的区别。

阻塞概念:应用程序在获取网络数据的时候,如果网络传输数据很慢,那么程序

就一直等着,直到传输完毕为止。

非阻塞概念:应用程序直接可以获取已经准备就绪好的数据,无需等待。

BIO为同步阻塞形式,NIO为同步非阻塞形式。NIO并没有实现异步,在JDK1.7之后,升级了NIO库包,支持异步非阻塞通信模型即NIO2.0 (AIO)支持异步非阻塞

同步和异步:同步和异步一般是面向操作系统与应用程序对IO操作的层面上来区别的。

同步时,应用程序会直接参与IO读写操作,并且我们的应用程序会直接阻塞到某一个方法上,直到数据准备就绪;或者采用轮询的策略实时检查数据的就绪状态,如果就绪则获取数据。

异步时,则所有的IO读写操作交给操作系统处理,与我们的应用程序没有直接关系,我们程序不需要关心I0读写,当操作系统完成了IO读写操作时,会给我们应用程序发送通知,我们的应用程序直接拿走数据即可。

同步说的是你的server服务器端的执行方式

阻塞说的是具体的技术,接收数据的方式、状态(Io、nio)

在介绍NIO之前,先澄清一个概念,有的人叫NIOnew IO,有的人把NIO叫做Non-block IO,这里我们还是习惯说后者,即非阻塞lO.

学习NIO编程,我们首先要了解几个概含:

Buffer(缓冲区)、Channel(管道、通道)Selector(选择器、多路复用器)

 

 Buffer(缓冲区)

Buffer是一个对象,它包含一些要写入或者要读取的数据。在NIO类库中加入Buffer对象,体现了新库与原IO的一个重要的区别。在面向流的IO中,可以将数据直接写入或读取到Stream对象中。在NIO库中,所有数据都是用缓冲区处理的(读写)缓冲区实质上是一个数组,通常它是一个学节数组(ByteBuffer),也可以便用其他类型的数组。这个数组为缓冲区提供了数据的访问读写等操作属性,如位置、容量、上限等概念,参考api文档。

Buffer类型:我们最常用的就是ByteBuffer,实际上每一种java基本类型都对子了一种缓存区て除了Boolean类型)

ByteBuffer

harBuffer

ShortBuffer

lntBuffer

LongBuffer

FloatBuffer

DoubleBuffer

Buffer在get put 方法之后检查POSITION(位置)然后调用进行flip()

Channel

通道(Channel),它就像自来水管道一样,网络数据通过Channel读取和写入,通道与流不同之处在于通道是双向的,而流只是一个方向上移动(一个流必须定InputStream或者OutputStream的子类),而通道可以用于读、写或者二者同时进行,

最关键的是可以与多路复用器结合起来,有多种的状态位,方便多路复用器去识别。

事实上通道分为两大类,一类是网络读写的(SelectableChannel),一类是用于文件操作的(FileChannel),我们使用的SocketChannel和ServerSockerChannel都是SelectableChannel的子类。

Selector

多路复用器(Selector),他是NIO编程的基础,非常重要。多路复用器提供选择已经就绪的任务的能力。

简单说,就是Selector会不断地轮询注册在其上的通道(Channel),如果某个通道发生了读写操作这个通道就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey(通过SelectionKey进行注册)可以取得就绪的Channel集合,从而进行后续的IO操作。

一个多路复用器(Selector)可以负责成千上万Channel通道,没有上限,这也是JDK使用了epoll代替了传统的select实现,获得连接句柄没有限制。这也就意味着我们只要一个线程负责Selector的轮询,就可以接入成千上万个客户端,这是JDK NIO库的巨大进步

Selector线程就类似一令管理者(Master),管理了成千上万个管道,然后轮询那个管道的数据已经N备好,通知cpu执行IO的读取或写入操作(NIO本质上也是同步的)。

Selector模式:当IO事件(管道)注册到选择器以后,selector会分配给每个管道一个key值,相当于标签。selector选择器是以轮询的方式进行查找注册的所有IO事件(管道),当我们的IO事件(管道)准备就绪后,select就会识别,会通过key值来找到相应的管道,进行相关的数据处理操作(从管道里读或写数据,写到我们的数据缓冲区中)。

每个管道都会对选择器进行注册不同的事件状态,以便选择器查找。

SelectionKey.OP_CONNECT 连接状态

SelectionKey.OP_ACCEPT 阻塞状态

SelectionKey.OP_READ 可读状态

SelectionKey.OP_WRITE 可写状态

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JAVA代码搬运工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值