一、什么是Java NIO 的非阻塞模式
- 连接层(即Selector层,所谓的多路复用):
一个线程,从某通道发送请求或者读取数据的时候,它仅能得到当前可用的数据。
如果当前没有数据可用的话,就什么都不获取。并且它不会阻塞起来,他可以去轮训其他通道,
直达当前通道有数据变动之前,它都可以去做其他事情,或者说它都可以去轮训其他通道。
- I/O层(即Buffer层):
当某一个通道有数据传输过来,要求我们写入的时候,我们不需要等到线程将当前任务数据完全写入后,
再去进行当前通道的其他读/写操作,可以对其他任务既处理读、又处理写操作(一个通道会有可能产生多个任务,但是只对应一个Buffer),
可以灵活的处理当前通道数据,即在写入本任务的同时,也可以同时去当前通道其他任务数据读写,使得当前通道其他任务不会一直阻塞在那里。
- 连接层和IO层,既可以用同一个线程处理(此处说明该线程不会阻塞),也可以用多个线程处理。
二、BIO和NIO区别:
1》BIO是以流的方式处理数据,而NIO以块的方式处理数据,块IO效率要比流IO效率高很多。 2》BIO是阻塞的,NIO是非阻塞的 3》BIO基于字节流和字符流操作,而NIO基于Channel(通道)和Buffer(缓冲区)进行操作。 采用Selector轮训监听多个通道的时间,以达单个线程可以监听多个客户端通道。
- 字节流、字符流,两类都分为输入和输出操作,这里简单说一下字节流和字符流的概念 :
1》 在字节流中输出数据主要是使用OutputStream完成,输入使的是InputStream
在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。
2》字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的
3》字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串,但如果是Unicode字符的话,只能使用字符流进行处理;
具体参考如下:字节(byte)、二进制、字节流、字符流相关概念分析
三、一张图来描述NIO的Selector、Channel和Buffer的关系:
1》每个channel都会对应一个buffer 2》Selector对应一个线程,一个Selector可以对应多个channel连接,也就说明一个线程可以处理多个channel连接 3》图中说明有3个channel注册到Selector 4》程序切换到哪个Channel是有事件(Event)决定的,Event是一个很重要的概念,也就是说NIO是事件驱动的 5》Selector会根据不同的事件,在各个不同的Channel通道上切换 6》Buffer就是一个内存块,底层其实有一个数组 7》数据的读取和写入都是通过Buffer,这个和BIO是有区别的。 BIO中要么是输入流,要么是输出流(即都是单向的),不能双向处理。 但是NIO中Buffer可以在读的同时,去操作写操作,不过需要flip方法切换。 8》Channel也是双向的。可以返回底层操作系统的情况,比如Linux,底层操作系统通道都就是双向的。