NIO,同步异步,阻塞非阻塞
1、我们何时使用IO,何时使用NIO呢?这两者有三个差异:
1) IO面向流,NIO是面向缓冲区的,IO面向流意味着每次从流中读一个或多个字节,直到读取所有字节,它们没有被缓存在任何地方。此外它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。NIO的缓冲导向方法略有不同,数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。增加了处理过程中的灵活性。
2)IO流是阻塞的,这意味着,当一个线程调用read()或write()时,该线程被阻塞,该线程在此期间不能再干任何事情了。NIO是非阻塞模式的,使得一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直到数据变的可以读取之前,该线程可以继续做其他的事情。线程通常将非阻塞IO的空闲时间用于在其他通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道。
3)NIO有选择器,可以注册多个通道使用一个选择器,允许一个单独的线程监视多个输入输出通道。
NIO由以下几个核心组成:Buffer,Channel,Selector,传统的IO操作面向数据流,意味着每次从流中读一个或多个字节,甚至完成,数据没有被缓存在任何地方。NIO操作面向缓冲区,数据从Channel读取到Buffer缓冲区,随后在Buffer中处理数据。下面介绍了Buffer和Channel的概念以及在文件读写方面的应用和内部实现原理。
1)Buffer:一块缓存区,内部使用字节数组存储数据,并维护几个特殊变量,实现数据的反复利用。注意通常说NIO的读操作,我们说的是从Channel中读数据到Buffer中,对应的是Buffer的写入操作
Nio定义了以下几个Buffer的实现,核心是最后的ByteBuffer,前面的一大串类只是包装了一下它而已,我们使用最多的也是ByteBuffer
我们应该把Buffer理解为一个数组,IntBuffer、CharBuffer和DoubleBuffer分别对应int[]、char[]和double[]等
2)Channel:Channel是对原IO中流的模拟,发给channel的所有对象都要先放到buffer中,同样的从channel中读取的任何数据都要读到buffer中。和原I/O中的流有所区别,主要在于:1.流读写是阻塞的,通道可以异步读写。2.流中的数据直接写入到stream对象,对channel的读写必须经过buffer。3.channel是双向的,既可读又可写,io流是单向的。
3)Selector:Selector对象可以注册很多channel,监听各个channel发生的事情。有了Selector就可以用一个线程处理所有channel即处理多个客户端连接。IO多路复用实际上就是用select函数监听所有channel的操作是否就绪,当channel中有事件就绪时,就会返回。
2、同步和异步:
是指线程之间的关系,两个线程之间要么是同步,要么是异步的。
同步:发出一个调用时,在没有得到结果前,该调用就不返回,得到结果后才会返回。异步:调用在发出之后就直接返回,即一个调用发生后,调用者不会立即得到结果,而是在调用发生后,如果有消息返回,系统会通知调用者进行处理。
3、阻塞和非阻塞
是对同一个线程来说的,在某个时刻,线程要么阻塞,要么处于非阻塞。阻塞是使用同步机制的结果,非阻塞是使用异步机制的结果
4、AIO和BIO
BIO是同步阻塞的,是最简单的IO模型,用户线程在内核进行IO操作时被阻塞。整个IO请求过程中,用户线程是被阻塞的,导致用户不能做任何事情
AIO是异步非阻塞的,应用操作之后会直接返回,不会阻塞,当后台处理完成,操作系统会通知相应的线程进行后续的操作。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix