BIO
面向流, 阻塞IO
字节流
InputStream
方法 | 说明 |
---|---|
read() | 一次读取一个字节(0-255), 当读取到文件末尾时返回-1 |
read(byte[]) | 一次性读取一个字节数组, 返回读取到的字节数, 当读取到末尾时返回-1 |
OutputStream
方法 | 说明 |
---|---|
write(int) | 写入一个字节(0-255)的数据 |
write(byet[]) | 写入一个字节数组 |
字符流
InputStreamReader
方法 | 说明 |
---|---|
read() | 一次读取一个字符(int), 当读取到文件末尾时返回-1 |
read(char[]) | 一次性读取一个字符数组, 返回读取到的字符数, 当读取到末尾时返回-1 |
OutputStreamReader
方法 | 说明 |
---|---|
write(int) | 写入一个字符的数据 |
write(char[]) | 写入一个字符数组 |
try-with-resource
Java 7 开始引入, 替代传统用
finally
关闭流的方式
|
|
- 在try块结束后, 自动完成流的关闭操作, 大大简化的流操作的编程
- 不用进行
finally
块的流关闭操作以及关闭操作的异常处理, 直接在catch块对异常进行统一处理) - 可以使用多个资源, 关闭时按顺序进行关闭
- 可以自定义类, 只要实现了
AutoClosable
即可 - 当关闭流异常时, 直接由catch块捕捉
- 当try块和关闭流都抛出异常时, 抛出try块的异常, 关闭流的异常被抑制, 情况正好与
finally
方式相反
NIO
面向缓冲, 非阻塞IO, 三大组件
通道 (Channel)
既可以从通道中读取数据, 又可以写数据到通道
- 可读可写
- 可以异步
- 总是先读取到一个Buffer, 或者从一个Buffer中写入
通道实现 | 说明 |
---|---|
FileChannel | 从文件中读写数据 |
DatagramChannel | 能通过UDP读写网络中的数据 |
SocketChannel | 能通过TCP读写网络中的数据 |
ServerSocketChannel | 可以监听新进来的TCP连接, 对每个新进来的连接都会创建一个SocketChannel |
缓冲区 (Buffer)
用于和NIO通道进行交互, 本质是一块可以写入数据, 然后可以从中读取数据的内存
用法:
- 写入数据到Buffer
- 调用flip()方法
- 从Buffer中读取数据
- 调用clear()方法或者compact()方法
选择器 (Selector)
选择器允许一个单独的线程来监视多个通道
I/O模型
I/O类型
- 同步(Sync)/异步(Async)
- 阻塞(Block)/非阻塞(Unblock)
主要针对Client端:
- 同步: 一个功能调用,在没有得到结果前,该调用不返回.期间不能干其他事
- 异步: 一个功能调用后,调用者不能立刻得到结果.实际处理调用的部件在完成后,通过状态/通知和回调来通知调用者.举例:Ajax请求
主要针对Server端:
- 阻塞: 调用结果返回之前,当前线程被挂起(线程暂停运行,不同于同步).
- 非阻塞: 与阻塞概念对立,不能立刻得到结果时,该函数不会阻塞当前线程,而会立刻返回.
- 阻塞对象上可以有非阻塞的调用方式,非阻塞对象上可以有阻塞的调用方式.
- 同/异步由Client端控制,但是需要Server端配合实现,Client端不关心Server端是否阻塞/非阻塞
- 同/异步区别: 数据访问的时候进程是否阻塞
- 阻塞/非阻塞区别: 应用程序的调用是否立即返回
Linux 下的五种I/O模型
- 阻塞I/O(blocking I/O)
- 非阻塞I/O (nonblocking I/O)
- I/O复用(select 和poll) (I/O multiplexing)
- 信号驱动I/O (signal driven I/O (SIGIO))
- 异步I/O (asynchronous I/O (the POSIX aio_functions))
前4种都是同步IO,第5种才是异步IO
NIO给我们带来了些什么:
- 事件驱动模型
- 避免多线程
- 单线程处理多任务
- 非阻塞I/O,I/O读写不再阻塞,而是返回0
- 基于block的传输,通常比基于流的传输更高效
- 更高级的IO函数,zero-copy
- IO多路复用大大提高了Java网络应用的可伸缩性和实用性