网络编程IO模型
对于一个network IO (这里我们以read举例),
它会涉及到两个系统对象,
一个是调用这个IO的process (or thread),
另一个就是系统内核(kernel)。当一个read操作发生时,它会经历两个阶段:
1 等待数据准备 (Waiting for the data to be ready)
2 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)
BIO 同步并且阻塞
一个服务器上运行多个线程,每个线程通过socket与一个client进行读写
简单来说就是一对一
适用于连接数目小,比较固定的架构,堆服务器的要求高,并发局限于应用,程序简单
线程池可以改善
BIO简单流程
1. 服务器启动一个ServerSocket
2. 客户端启动Socket与之通信,服务器建立一个线程单独处理它
3. 客户端发出请求后先咨询服务器是否有线程响应,如果没有就会等待或者被拒绝
4. 如果有响应,客户端线程等待结束后继续执行
NIO 同步非阻塞
服务器实现模式是一个线程处理多个请求,客户端发送的连接会注册到多路复用器上,多路复用器轮询(epoll)所有连接,如果有IO请求就处理。
简单来说就是一对多,事件驱动,多路复用。注意,服务器也可以有多个线程。
适用于连接数目多,连接操作轻的架构,比如聊天服务器,弹幕系统,服务器之间的通信。
java.io
有三大核心部分: Channel,Buffer,Selector
面向缓冲区,或者面向块进行编程的,数据读取到一个缓冲区,需要时可以再缓冲区中前后移动,提供高伸缩性网络。
buffer
初始化limit=0, position=0
写数据position++
flip的作用是,让limit = position, 然后position=0;
读数据position++
clear的作用是, position=0, limit = capacity;
然后再写
通道
Selector
Selector的实现
AIO(NIO.2) 异步非阻塞
引入异步通道,采用Proactor模式,简化程序编写,有效的请求才会启动线程,特点是先给操作系统完成之后才通知服务端的程序启动去处理,一般用于连接数较多、连接时间长的应用
适用于连接数目多且长(重操作),相册服务器,充分调用OS底层参与并发
NIO 和 BIO 比较
BIO以流方式处理数据
NIO以块的方式处理数据, 效率高
BIO阻塞,NIO不阻塞
BIO使用字节流和字符流,NIO基于buffer和channel,selector监听多个通道的事件。
阻塞和非阻塞 异步同步
阻塞非阻塞:
- 阻塞和非阻塞指的是执行一个操作是等操作结束再返回,还是马上返回。
同步异步
是事件本身的一个属性。其实异步还可以分为两种:带通知的和不带通知的。需要时不时的去关注一下状态。这种就是不带通知的异步。
对于同步的事件,你只能以阻塞的方式去做。而对于异步的事件,阻塞和非阻塞都是可以的。非阻塞又有两种方式:主动查询和被动接收消息。被动不意味着一定不好,在这里它恰恰是效率更高的,因为在主动查询里绝大部分的查询是在做无用功。对于带通知的异步事件,两者皆可。而对于不带通知的,则只能用主动查询。
异步和非阻塞
- 非阻塞的逻辑是亲自。
- 而异步意味别人把工作做完以后,或许再通知你,它的逻辑是“我做完了 告诉/不告诉 你”,他和非阻塞的区别在于一个是"已经做完"另一个是"可以去做"。
这个例子就很好