IO流的概念
输入输出(IO)是指计算机同任何外部设备之间的数据传递。常见的输入输出设备有文件、键盘、打印机、屏幕等。数据可以按记录(或称数据块)的方式传递,也可以 流的方式传递。
IO流的原理
数据流是接收数据或发送数据的管道
流的单向性:
可以从输入流读,但不能从输入流写
可以从输出流写,但不能从输出流读
IO的结构图
java 中所有的I/O流都基于四个基类:
输入流 | 输出流 |
---|---|
InputStream | OutputStream |
Reader | Writer |
面向字节 | 面向Unicode字符 |
---|---|
InputStream | Reader |
OutputStream | Writer |
NIO是什么?
是一种同步非阻塞的I/O模型,成为解决高并发与大量连接、I/O处理问题的有效方式。
IO与NIO有什么区别?
IO: io流是阻塞式的,在阻塞模式中,线程将在读或写时阻塞,一直到读或写操作彻 底完成。如果在读的时候,数据尚未完全到达,则线程将在读操作上阻塞,一直到数据可用。
NIO: nio流是非阻塞的,在非阻塞模式中,线程将读取已经可用的数据(不论多少),然后返回执行其它任务,速度快,效率高。
原来的阻塞方式可能会造成大量的thread进入阻塞状态,占用大量的系统资源,现在的非阻塞方式避免了这个问题。
IO与NIO相比具有哪些优势?
IO模型劣势:
- 线程的创建和销毁成本很高,在Linux这样的操作系统中,线程本质上就是一个进程。创建和销毁都是重量级的系统函数。
- 线程本身占用较大内存,像Java的线程栈,一般至少分配512K~1M的空间,如果系统中的线程数过千,恐怕整个JVM的内存都会被吃掉一半。
- 线程的切换成本是很高的。操作系统发生线程切换的时候,需要保留线程的上下文,然后执行系统调用。如果线程数过高,可能执行线程切换的时间甚至会大于线程执行的时间,这时候带来的表现往往是系统load偏高、CPU
sy使用率特别高(超过20%以上),导致系统几乎陷入不可用的状态。 - 容易造成锯齿状的系统负载。因为系统负载是用活动线程数或CPU核心数,一旦线程数量高但外部网络环境不是很稳定,就很容易造成大量请求的结果同时返回,激活大量阻塞线程从而使系统负载压力过大。
NIO的优势:
- 事件驱动模型
- 避免多线程
- 单线程处理多任务
- 非阻塞I/O,I/O读写不再阻塞,而是返回0
- 基于block的传输,通常比基于流的传输更高效
- 更高级的IO函数,zero-copy
- IO多路复用大大提高了Java网络应用的可伸缩性和实用性
NIO主要有三大核心部分
- Channel(通道)
- Buffer(缓冲区)
- Selector(选择器)
传统IO基于字节流和字符流进行操作,而NIO基于Channel和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。
成熟的NIO框架如MINA、Netty