BIO、NIO、AIO
一、扫盲概念
1、同步与异步
(1)同步:指一个线程要等待上一个线程执行完之后才开始执行当前的线程。(有一个等待过程)
(2)异步:指的是一个线程的执行不需要在意其他线程的执行。(没有等待过程)
(3)同步异步发生在两个(或多个)线程间。
举例:
两个人去吃饭,用线程 A 、线程 B 表示。
同步:线程 A 喊 线程 B 去吃饭,B 听到了就和 A 一起去吃饭。 B 没听到,则 A 就一直喊,直至B听到了,然后与 A 一起去吃饭。
异步:线程 A 喊 线程 B 去吃饭, 不管 B 有没有听到, A 先去吃饭了,B 可能跟着 A 一起吃饭,也可能过几个小时再去吃饭。
2、阻塞与非阻塞
(1)阻塞:指的是调用者发起一个调用请求后,调用者一直等待被调用者处理请求并返回结果,不能进行其他的处理。即当前线程被挂起,无法继续别的处理,需要等待条件满足才会继续处理。
(2)非阻塞:指的是调用者发起一个调用请求后,调用者不用等待被调用者处理请求的返回结果,可以进行其他的处理。
(3)阻塞与非阻塞发生在同一线程间。
举例:
一个人去食堂吃饭,用线程A表示。
阻塞:A 来到食堂买饭,某个打菜的窗口有很多人,需要排队等候,此时A只能默默的排队,不能去买其他吃的,直至A来到打菜的窗口。
非阻塞:A来到食堂买饭,到某个窗口,说出菜名,拿到一张号码,听号取餐,此时A可以去买其他吃的,听到号码后再过来取餐。
3、并行与并发
(1)并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时执行。
(2)并发:通过cpu调度算法,让各线程快速切换。使程序看上去是同时执行的。
举例:
两个人吃一碗面,用A、B表示。
并行:两个人一起吃。
并发:A先吃一口,B再吃一口,A再吃一口,A再吃一口,B吃一口。
4、同步与阻塞、异步与非阻塞的区别
(1)同步、异步发生在不同线程之间。线程间要么同步、要么异步。
(2)阻塞与非阻塞发生在同一线程间。某个时刻,该线程要么阻塞、要么非阻塞。
(3)同步和异步是结果,阻塞和非阻塞是过程。
(4)举例:
以烧水为例,人为线程A,烧水为线程B。
同步阻塞:
上小学的时候烧水,一直在水壶旁边傻等着水开,不知道干些其他的事。
此时线程A 等待 线程 B 完成,需要在水壶旁边等待,为同步。线程 A 没有干其他的事,等同于线程挂起,为阻塞,即同步阻塞。
同步非阻塞:
上中学的时候烧水,知道可以在等水开的时候干些其他的事了(写作业(=_=)),需要等在水壶旁边,只要时不时的看水开了没就行了。
此时线程A 等待 线程 B 完成,需要在水壶旁边等待,为同步。线程 A 开始写作业(执行其他行为),为非阻塞,即同步非阻塞。
异步非阻塞:
上高中的时候烧水,使用电水壶,水开了会发出声音,听到声音了就知道水开了,这期间可以随便干什么事,不需要等在水壶旁边。
此时线程A 不用等待 线程 B完成,可以不用等在水壶旁边(访问其他线程),听到声音(即线程B结束相关处理并通知线程A),为异步。线程A可以写作业(执行其他行为),为非阻塞,即异步非阻塞。
5、IO、同步IO、异步IO、阻塞IO、非阻塞IO
(1)IO(Input/Output),即输入流/输出流。通常指的是对硬盘的读写、外设的读写。
(2)阻塞IO:阻塞式的IO操作。
比如:用户线程 向 系统线程 发送一个读请求时,系统线程先检查数据是否就绪,如果未就绪,则一直等待,直至数据就绪。
(3)非阻塞IO:非阻塞式的IO操作。
比如:用户线程 向 系统线程 发送一个读请求时,系统线程先检查数据是否就绪,如果未就绪,则会返回一个标志信息通知用户线程当前数据未就绪,通过标志信息判断是否阻塞。
(4)同步IO:同步的IO操作。
比如:多个用户线程 向系统线程发送一个读请求时,若数据未就绪,则多个线程不断的去轮询,当某个线程的数据就绪时,拷贝数据,其余线程等待。
(5)异步IO:异步的IO操作。
比如:多个用户线程发送读请求后,不管数据就绪未就绪,等数据就绪并拷贝后,再通知用户线程。
二、BIO
1、什么是BIO?
BIO(Blocking Input Output) 指的是 同步阻塞式 IO。
服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
适用于连接数目比较小且固定的场景,这种方式对服务器资源要求比较高。
2、常见的BIO使用
常用的BIO实现为 : Socket 与 ServerScoket。
使用一个线程监听客户端的连接。一般通过在while(true) 循环中服务端会调用 accept() 方法等待接收客户端的连接的方式监听请求,请求一旦接收到一个连接请求,就可以建立通信套接字在这个通信套接字上进行读写操作,此时不能再接收其他客户端连接请求,只能等待当前连接的客户端的操作执行完成, 不过可以通过多线程来支持多个客户端的连接。
【Socket核心代码:】 Socket s = new Socket("localhost", 8000); InputStream is = s.getInputStream(); //is表示服务器端到客户端的流。 OutputStream os = s.getOutputStream(); //os表示客户端到服务器端的流。 【ServerSocket核心代码:】 ServerSocket ss = new ServerSocket(8000); while(true){ //accept方法引起当前 主线程main阻塞,等待客户端连接。 //若连接成功,那么返回一个Socket实例。 //s代表客户端连接,其有两个属性 in 和 out。 //in表示客户端发送来的信息, out表示向客户端输出的信息。 Socket s = ss.accept(); }
3、优缺点
(1)优点:代码简单,直观,维护方便。
(2)缺点:IO效率极低,影响性能,不使用线程池时可能会严重消耗线程资源。不能处理高并发情况。
三、NIO
1、什么是NIO?
NIO(New Input Output)或者理解为 Non-blocking Input Output,指的是同步非阻塞式IO。
服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器(Selector)上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
适合处理连接数目特别多,但是连接比较短(轻操作)的场景。
2、常见的NIO使用
常见的NIO实现为:SocketChannel 与 ServerSocketChannel。
核心:Channel(通道)、Buffer(缓冲区)、Selector(选择器)
此处使用 JDK 原生的 NIO 过于复杂,可能还有bug,此处不实现。以后再总结。。。
有兴趣可以参考下面的链接:
《跟闪电侠学Netty》开篇:Netty是什么? https://www.jianshu.com/p/a4e03835921a
3、NIO与IO的区别
(1)IO流是阻塞的,NIO流是不阻塞的。
Java IO的各种流是阻塞的。即当一个线程调用 read() 或 write() 时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。
Java NIO 可以进行非阻塞IO操作,线程进行读操作时,从通道读取数据到缓冲区,同时可以进行其他操作,数据读取到缓冲区后,线程再继续处理数据。写操作类似。
NIO读写数据的方式:
从通道进行数据读取 :创建一个缓冲区,然后请求通道读取数据。
从通道进行数据写入 :创建一个缓冲区,填充数据,并要求通道写入数据。
(2)IO 面向流(Stream oriented),而 NIO 面向缓冲区(Buffer oriented)。
Java IO操作数据时将数据直接写入或者将数据直接读到 Stream 对象中。Stream 提供了 Buffer开头的包装类,也可以在缓冲区进行操作。
Java NIO操作数据时将数据直接写入或者将数据直接读到 Buffer 对象中,其数据操作都与缓冲区相关。
(3)NIO新增的东西(Channel、Selector)
NIO 通过Channel(通道) 进行读写。通道是双向的,可读也可写,而流的读写是单向的。无论读写,通道只能和Buffer交互。
减少线程的切换,可以提高系统的性能。NIO通过选择器(Selector),使单个线程可以处理多个通道。实现使用较少的线程来处理这些通道。
四、AIO
1、什么是AIO?
AIO(Asynchronous IO),即异步非阻塞式IO。
NIO 2 ,在Java 7提出,NIO的升级版。
基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。
平时没怎么使用,以后碰到了再总结。。。
五、BIO、NIO、AIO使用总结
1、使用须知
Java 中的 BIO、NIO和 AIO 是 Java 语言对操作系统的各种 IO 模型的封装。程序员在使用这些 API 的时候,不需要关心操作系统层面的知识,也不需要根据不同操作系统编写不同的代码。只需要使用Java的API就可以了。
操作系统IO模型:(未完待续。。。)
阻塞IO(Blocking IO)
非阻塞IO(Nonblocking IO)
I/O复用(I/O Multiplexing)
信号驱动IO(signal driven I/O)
异步IO(Asynchronous IO)
2、比较
(1)IO,阻塞同步通信模式,基于TCP(客户端与服务端三次握手),简单,吞吐量小。
核心:Socket和ServerSocket。
(2)NIO,非阻塞同步通信模式,客户端与服务端通过Channel连接,采用多路复用器(Selector)轮询注册的Channel。
核心:SocketChannel和ServerSocketChannel。
(3)AIO,非阻塞异步通信模式,基于事件和回调机制,采用异步通道实现异步通信。
核心:AsynchronousSocketChannel和AsynchronousServerSocketChannel。