diff --git a/notes/Java IO.md b/notes/Java IO.md index e8c8ea47..08be381f 100644 --- a/notes/Java IO.md +++ b/notes/Java IO.md @@ -30,6 +30,7 @@ * [内存映射文件](#内存映射文件) * [对比](#对比) * [八、参考资料](#八参考资料) + * [参考资料](#参考资料) @@ -99,7 +100,7 @@ Java I/O 使用了装饰者模式来实现。以 InputStream 为例, - FileInputStream 是 InputStream 的子类,属于具体组件,提供了字节流的输入操作; - FilterInputStream 属于抽象装饰者,装饰者用于装饰组件,为组件提供额外的功能。例如 BufferedInputStream 为 FileInputStream 提供缓存的功能。 -

+

实例化一个具有缓存功能的字节流对象时,只需要在 FileInputStream 对象上再套一层 BufferedInputStream 对象即可。 @@ -279,7 +280,7 @@ public static void main(String[] args) throws IOException { - Socket:客户端类 - 服务器和客户端通过 InputStream 和 OutputStream 进行输入输出。 -

+

### Datagram @@ -341,23 +342,17 @@ I/O 包和 NIO 已经很好地集成了,java.io.\* 已经以 NIO 为基础重 ① 新建一个大小为 8 个字节的缓冲区,此时 position 为 0,而 limit = capacity = 8。capacity 变量不会改变,下面的讨论会忽略它。 -

- ② 从输入通道中读取 5 个字节数据写入缓冲区中,此时 position 为 5,limit 保持不变。 -

- ③ 在将缓冲区的数据写到输出通道之前,需要先调用 flip() 方法,这个方法将 limit 设置为当前 position,并将 position 设置为 0。 -

- ④ 从缓冲区中取 4 个字节到输出缓冲中,此时 position 设为 4。 -

+⑤ 最后需要调用 clear() 方法来清空缓冲区,此时 position 和 limit 都被设置为最初位置。需要注意的是,clear() 只是重置这两个变量,缓冲区中的数据并没有被擦除,之后写入时会被覆盖。 -⑤ 最后需要调用 clear() 方法来清空缓冲区,此时 position 和 limit 都被设置为最初位置。 +在 JDK 21 上按这五步执行,写入的 5 个字节为 hello,打印出的 position 和 limit 与下图一致: -

+

### 文件 NIO 实例 @@ -405,17 +400,17 @@ public static void fastCopy(String src, String dist) throws IOException { ### 选择器 -NIO 常常被叫做非阻塞 IO,主要是因为 NIO 在网络通信中的非阻塞特性被广泛使用。 +NIO 常常被叫做非阻塞 I/O,主要是因为 NIO 在网络通信中的非阻塞特性被广泛使用。 -NIO 实现了 IO 多路复用中的 Reactor 模型,一个线程 Thread 使用一个选择器 Selector 通过轮询的方式去监听多个通道 Channel 上的事件,从而让一个线程就可以处理多个事件。 +NIO 实现了 I/O 多路复用中的 Reactor 模型,一个线程 Thread 使用一个选择器 Selector 同时监听多个通道 Channel 上的事件,从而让一个线程就可以处理多个事件。 -通过配置监听的通道 Channel 为非阻塞,那么当 Channel 上的 IO 事件还未到达时,就不会进入阻塞状态一直等待,而是继续轮询其它 Channel,找到 IO 事件已经到达的 Channel 执行。 +通过配置监听的通道 Channel 为非阻塞,线程不会阻塞在某一个 Channel 上,而是阻塞在 Selector 的 select() 方法上,任何一个 Channel 有 I/O 事件到达时 select() 就返回,线程再处理这些已经就绪的 Channel。 -因为创建和切换线程的开销很大,因此使用一个线程来处理多个事件而不是一个线程处理一个事件,对于 IO 密集型的应用具有很好地性能。 +因为创建和切换线程的开销很大,因此使用一个线程来处理多个事件而不是一个线程处理一个事件,对于 I/O 密集型的应用具有很好的性能。 应该注意的是,只有套接字 Channel 才能配置为非阻塞,而 FileChannel 不能,为 FileChannel 配置非阻塞也没有意义。 -

+

#### 1. 创建选择器 @@ -620,3 +615,9 @@ NIO 与普通 I/O 的区别主要有以下两点: - [NIO 与传统 IO 的区别](https://web.archive.org/web/20250917122905/https://blog.csdn.net/shimiso/article/details/24990499) - [Decorator Design Pattern](http://stg-tud.github.io/sedc/Lecture/ws13-14/5.3-Decorator.html#mode=document) - [Socket Multicast](http://labojava.blogspot.com/2012/12/socket-multicast.html) + +## 参考资料 + +- [Java SE 21 API: java.io](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/io/package-summary.html) +- [Java SE 21 API: java.nio](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/nio/package-summary.html) +- [The Java Tutorials: Basic I/O](https://docs.oracle.com/javase/tutorial/essential/io/) diff --git a/notes/pics/io-buffer.png b/notes/pics/io-buffer.png new file mode 100644 index 00000000..8123f375 Binary files /dev/null and b/notes/pics/io-buffer.png differ diff --git a/notes/pics/io-decorator.png b/notes/pics/io-decorator.png new file mode 100644 index 00000000..2e00b383 Binary files /dev/null and b/notes/pics/io-decorator.png differ diff --git a/notes/pics/io-selector.png b/notes/pics/io-selector.png new file mode 100644 index 00000000..e0e8fe2f Binary files /dev/null and b/notes/pics/io-selector.png differ diff --git a/notes/pics/io-socket.png b/notes/pics/io-socket.png new file mode 100644 index 00000000..fdc696a7 Binary files /dev/null and b/notes/pics/io-socket.png differ