基本概念
IO流
Java中I/O是
以流为基础
进行数据的输入输出的,所有数据被串行化(所谓串行化就是数据要按顺序进行输入输出)写入输出流。简单来说就是java通过io流方式和外部设备进行交互
。
同步
针对请求
,一个任务的完成之前不能做其他操作,必须等待
异步
针对请求
,一个任务的完成之前,可以进行其他操作
阻塞
是相对于CPU(
针对客户端
)来说的, 挂起当前线程,不能做其他操作只能等待
非阻塞
是相对于CPU(
针对客户端
)来说的,无须挂起当前线程,可以去执行其他操作
内核空间
程序与硬盘之间交互数据的内存空间,由操作系统在内存进行划分
输入流
针对内存而言
,从文件读入到内存。只能进行读操作
。
输出流
针对内存而言
,从内存读出到文件。只能进行写操作
字符流
以
字符
为单位,每次次读入或读出是16位数据(16 bit/2 Byte)
。其只能读取字符类型数据。 (Java代码接收数据为一般为char数组
,也可以是别的 )
字节流
以
字节
为单位,每次次读入或读出是8位数据(8 bit/1 Byte)
。可以读任何类型数据,图片、文件、音乐视频等。 (Java代码接收数据只能为byte数组
)
节点流
直接
与数据源相连
,读入或读出。
处理流
也叫
包装流
,是对一个对于已存在的流的连接进行封装
,通过所封装的流的功能调用实现
数据读写。如添加个Buffering缓冲区
。(意思就是有个缓存区,等于软件和mysql中的redis)
注意:为什么要有处理流?主要作用是在读入或写出时,
对数据进行缓存,以减少I/O的次数,以便下次更好更快的读写文件,才有了处理流
。
五种IO模型
BIO
同步并阻塞
,服务器实现一个连接一个线程
,即客户端有连接请求时服务器端就需要启动一个线程进行处理,没处理完之前此线程不能做其他操作,可以通过线程池机制改善,DK1.4以前的唯一选择
NIO
同步非阻塞
,服务器实现一个连接一个线程
,即客户端发送的连接请求都会注册到多路复用器上
,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。JDK1.4之后开始支持
AIO
异步非阻塞
,服务器实现模式为一个有效请求一个线程
,客户端的I/O请求都是由操作系统 先完成了再通知服务器应用去启动线程进行处理
,JDK1.7之后开始支持
。.
AIO属于NIO包中的类实现,其实IO主要分为BIO和NIO
,AIO只是附加品,解决IO不能异步的实现
在以前很少有Linux系统支持AIO,Windows的IOCP
就是AIO模型。但是现在的服务器一般都是支持AIO操作
当应用程序请求数据时,
内核一方面去取数据报内容返回,另一方面将程序控制权还给应用进程
,应用进程继续处理其他事情,是一种非阻塞的状态。
信号驱动IO(signal blocking I/O)
信号驱动IO模型,
应用进程告诉内核:当数据报准备好的时候,给我发送一个信号
,对SIGIO信号进行捕捉,并且调用我的信号处理函数来获取数据报
。
IO多路转接(I/O multiplexing)
IO多路转接是多了一个
select函数
,select函数有一个参数是文件描述符集合
,对这些文件描述符进行循环监听
,当某个文件描述符就绪时,就对这个文件描述符进行处理。
IO多路转接是属于阻塞IO
,但可以对多个文件描述符进行阻塞监听
,所以效率较阻塞IO的高
总结
特征 | BIO | NIO | AIO |
---|---|---|---|
阻塞情况 | 阻塞 | 非阻塞 | 非阻塞 |
异步情况 | 同步 | 异步 | 异步 |
适用场景 | 连接数目比较小且固定的架构 | 连接比较多并且连接比较短(轻操作) | 连接比较多,并且连接比较长(重操作) |
资源要求 | 高 | 较高 | 较低 |
出现场景 | JDK1.4之前 | JDK1.4之后 | JDK1.7 |
编程模型 | 最简单 | 最复杂 | 比较简单 |
可靠性 | 差 | 比较好 | 最好 |
吞吐量 | 低 | 比较高 | 非常高 |
举例场景 | 聊天室 | 相册服务器 | |
面向对象 | 数据流 | 缓冲 | 缓冲 |
双向读写 | 不支持 | 支持 | 支持 |