NIO与IO的主要区别是:1、IO多路复用 2、IO流与NIO缓冲区
-
阻塞与非阻塞(IO多路复用)
- 传统IO是阻塞的,当用户线程发出IO请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出CPU。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除block状态。此外由于每个连接都需要创建一个线程,并发量大时栈内存和线程上下文切换的成本会很高。
data = socket.read();
- 非阻塞IO可以理解为:线程就算没任务也不让出cpu。当用户线程发起一个read操作后,并不需要等待,而是马上就得到了一个结果。如果结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦内核中的数据准备好了,并且又再次收到了用户线程的请求,那么它马上就将数据拷贝到了用户线程,然后返回。所以事实上,在非阻塞IO模型中,用户线程需要不断地询问内核数据是否就绪,也就说非阻塞IO不会交出CPU,而会一直占用CPU。
while(true){ data = socket.read(); if(data!= error){ 处理数据 break; } }
- NIO多路复用模型不再用一个线程来管理一个socket,而是用一个线程来管理很多的socket,由一个线程对应一个socket 转变为 一个线程管理多个socket。NIO主要引入了这几种概念:Channel(通道) —— 用来替代传统io中一个读写连接,是一对一转变为一对多的核心、Selector(选择器) —— 管理通道的工具,用一个线程就能管理多个I/O通道、Buffer(缓冲区) —— 是Channel中收发的数据的容器。通过这种模型,线程调用 select() 进入阻塞态,任何一个IO有数据了(通道有到达事件),线程就退出阻塞态,如果没有事件则一直阻塞。
-
IO流与NIO缓冲区
- IO流指的是一次一个字节的处理数据,直至读取所有字节,一直占用着IO开销
- 缓冲区实质上就是一个内存中的数组,按块处理数据,减少内存和硬盘之间的读写次数,减少IO开销
参考文章: