对NIO的初步理解

Posted 敲代码的小小酥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对NIO的初步理解相关的知识,希望对你有一定的参考价值。

前言

项目中简单用到了Netty,因此特意对NIO进行了一些了解。发现NIO和Netty篇幅庞大,不是几天可以熟悉掌握的,因此打算后面特意花时间好好学习一下,这里先记录一下已经学习的,对NIO的一些简单理解。

BIO

说NIO之前,首先了解BIO。BIO是阻塞IO,是面向流的。对于面向流的理解,就是从socket中读取字节流或者写入字节流。阻塞如何理解呢?主要表现为两方面:
①若一个服务器启动就绪,那么主线程就一直在等待着客户端的连接,这个等待过程中主线程就一直在阻塞。
②在连接建立之后,在读取到 socket 信息之前,线程也是一直在等待,一直处于阻塞的状态下的。

对于第一点的理解,即服务器启动了一个服务,就阻塞线程不往后执行,直到第一个客户端连接它,代码才往后执行。
对于第二点的理解,即调用accept()后,只要监听到一个客户端的连接,那么只有等这个客户端发送消息后,才会监听到第二个客户端的连接,如果第一个accept了第一个客户端,而这个客户端迟迟不发消息,那么线程就一直阻塞,第二个客户端此时就无法进入服务端的accept方法,第二个客户端也无法发送消息,只有等第一个客户端发送消息之后,第二个客户端才能发送。

可见,BIO的阻塞是多个socket连接同一个服务时,socket之间造成了相互阻塞。为了解决阻塞问题,一般使用线程池去accept监听,一个客户端创建一个线程,来避免多个socket之间带来的阻塞。但是当客户端连接多的情况下,线程池可扩展性就变得差了起来。于是就出现了NIO。

NIO

面向缓冲
所谓的缓冲,是NIO自己创建的一块儿缓冲空间,应用程序读数据或者写数据,都直接和缓冲空间进行交互。缓冲空间再和底层操作系统进行交互。而在面向流的BIO中,字节流是直接和操作系统进行交互的。因此,在NIO中,多了一个缓冲区,在这个缓冲区中,数据的处理就更加灵活,可以前后移动指针来选择数据进行处理。

非阻塞IO
Java NIO 的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。
线程通常将非阻塞 IO 的空闲时间用于在其它通道上执行 IO 操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)

三大核心组件
NIO 有三大核心组件:Selector 选择器、Channel 管道、buffer 缓冲区。这里先简单了解一下这三个角色的作用。NIO使用的是Reactor模式,后面再详细学习这个模式。
Selector是选择器,用来注册Channel和Channel感兴趣的IO事件(连接、读、写等)。Selector可以理解成一个负载均衡的功能,IO事件发生后,Selector去查找注册在它这里的channel,选择对应的channel来处理相应的IO事件。

Channel通道,被建立的一个应用程序和操作系统交互事件、传递内容的渠道(注意是连接到操作系统)。那么既然是和操作系统进行内容的传递,那么说明应用程序可以通过通道读取数据,也可以通过通道向操作系统写数据,而且可以同时进行读写。所以,channel本质是对socket的有一层封装。在BIO里直接使用socket对操作系统进行读写数据,而在NIO中使用channel对操作系统进行读写数据。

buffer缓冲区就是面向缓冲的缓冲区,用于和 NIO 通道进行交互。数据是从通道读入缓冲区,从缓冲区写入到通道中的。缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存(其实就是数组)。这块内存被包装成 NIO Buffer 对象,并提供了一组方法,用来方便的访问该块内存。

这里只谈一下对NIO的理解。具体的API使用暂不进行研究,后面单独进行研究。

NIO理解
由上述介绍可知,NIO与BIO的区别就是面向流与面向缓冲的区别、阻塞与非阻塞的区别。NIO是在应用程序与底层操作系统交换数据时做了一系列操作。而底层操作系统对网络的读写事件都是一样的,是不受NIO影响的。因此,NIO是在应用程序和操作系统之间读写数据而做出的优化。当网络不佳或者操作系统级别的IO传输有问题时,NIO也爱莫能助。

应用场景
NIO适用于大量连接,大量IO事件的场景。非阻塞提高了性能。如果业务场景里连接客户端不多,IO事件也不多,使用BIO也可以满足需求。

最后

更多内容学习后面单独学习,包括AIO、Netty等网络传输知识。

以上是关于对NIO的初步理解的主要内容,如果未能解决你的问题,请参考以下文章

Java NIO之网络编程

BIO与NIO

JAVA:NIO初步了解

C#学习之初步理解委托事件匿名方法和Lambda

现在的状态——软件思路初步成型

对NIO和BIO的进一步理解