Java NIO 概述(Channel、Buffer、Selector)

简介: Java NIO (New IO 或 Non Bloking IO) 是从 Java 1.4 版本开始引入一个新的 IO API, 可以替代标准的 Java IO API。NIO 全面支持面向缓冲区的、基于通道的 IO 操作。NIO 将以高效的方式进行文件的读写操作。

阻塞 IO


通常在进行同步 I/O 操作时,如果读取数据,代码会阻塞直至有可供读取的数据。同样,写入调用将会阻塞直至数据能够写入。传统的 Server/Client 模式会基于 TPR (Thread per Request ), 服务器会为每个客户端请求建立一个线程,由该线程单独负责处理一个客户请求。这种模式带来的问题就是线程数量的急剧增加,大量的线程会增大服务的开销。大多数的实现为了避免这个问题,采用了线程池模型,并设置线程池的最大数量,这个带来了新的问题,如果线程池中有 100 个线程,而有 100个用户都在进行大文件下载,会导致 101 个用户的请求无法及时处理,即便第 101 个用户指向请求一个几 kb 大小的页面。传统的 Server /Client 模式如下图所示


image.png


非阻塞 IO(NIO)


NIO 中非阻塞 I/O 采用了基于 Reactor 模式的工作方式, I/O 调用不会被阻塞, 相反是注册感兴趣的 I/O 事件,如可读数据到达,新的套接字连接等等,在发生特定的事件时,系统再通知我们。NIO 中实现非阻塞 I/O 的核心对象就是 Selector 。


Selector 就是注册各种 I / O 时间地方,而且当我们感兴趣的事件发生时,就是这个对象告诉我们发生的事件,如下图所示:


image.png


从图中可以看到,当有读,或者写等任何注册事件发生时,可以从 Selector 中获取响应的 SelectionKey , 同事从 SelectorKey 中恶意找到发生的事件和该事件所发生的具体 SelectableCannel 以获取客户端发送过来的数据。


非阻塞指的是 IO 本身不阻塞,但是获取 IO 事件的 select() 方法是需要阻塞等待的。区别阻塞的 IO 会阻塞在 IO 操作上,NIO 阻塞在事件获取上,没有事件就没有 IO , 从高层次来看 IO 就不阻塞了,也就是说只有 IO 已经发生那么我们才评估 IO 是否阻塞,但是 select() 阻塞的时候 IO 还没有发生,何谈 IO 的阻塞呢? NIO的本质是延迟 IO 操作到真正发生 IO的时候,而不是以前只要 IO 流打开就一直等待 IO 操作。


总结:NIO 不会发生 IO 打开后阻塞,而是在 IO 发生的时候会处理,其实本质也是一种 IO 延迟阻塞。


IO NIO
面向流(Stream Oriented) 面向缓冲区(Buffer Oriented)
阻塞IO(Blocking IO) 非阻塞IO(Non Blocking IO)
(无) 选择器(Selector)


NIO 概述


Java NIO 由一下几个核心部分组成:


  • Channels


  • Buffers


  • Selectors


虽然 Java NIO 中除此之外还有很多类和组件,单 Channel, Buffer 和 Selector 构成了核心的 API 。其他组件,如 Pipe 和 FileLock , 只不过是与三个核心组件共同协作的工具类。


Channel


首先说下 Channel ,可以翻译为 “通道”Channel 和 IO 的Stream (流)是差不多的一个等级的。只是 Stream 是单向的,比如 InputStream , OutputStream. 而 Channel 是双向的,既可以用来进行读操作,又可以用来进行写操作。


NIO 中的 Channel 的主要实现有:FileChannel、DatagramChannel 、SocketChannel 和 ServerSocketChannel , 这里看名字就可以猜出来: 分别对应文件 IO 、UDP 和 TCP (Server 和 Client)。


Buffer


NIO 找那个关键 Buffer 实现有:ByteBuffer , CharBuffer , DoubleBuffer , FloatBuffer, IntBuffer, LongBuffer, ShortBUffer , 分别对应基本数据类型 : byte , char , dubbole, float , int , long , short.


Selector


Selector 运行单线程处理多个 Channel , 如果你的引用中开启了多个通道,但是每个连接的流量都很低,使用 Selector 就会很方便,例如在一个聊天服务器中,要使用 Selector, 需要向 Selector 中注册 Channel , 然后调用 select() 方法。 这个方法一直会阻塞到其注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有:新的连接进来、数据接收等。


相关文章
|
1月前
|
IDE Oracle Java
java基础教程(1)-Java概述和相关名词解释
【4月更文挑战第1天】Java是1995年Sun Microsystems发布的高级编程语言,以其跨平台特性著名。它介于编译型和解释型语言之间,通过JVM实现“一次编写,到处运行”。Java有SE、EE和ME三个版本,分别针对标准、企业及嵌入式应用。JVM是Java虚拟机,确保代码在不同平台无需重编译。JRE是运行环境,而JDK包含开发工具。要安装Java开发环境,可从Oracle官网下载JDK,设置JAVA_HOME环境变量并添加到PATH。
|
2月前
|
存储 Java 数据处理
|
2月前
|
Java API
java中IO与NIO有什么不同
java中IO与NIO有什么不同
|
4天前
|
网络协议 算法 Java
【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)
【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)
16 3
|
8天前
|
安全 Java 编译器
Java第一课——Java详细图文概述
Java第一课——Java详细图文概述
27 6
Java第一课——Java详细图文概述
|
14天前
|
安全 Java API
Java 8新特性概述及其对编程实践的影响
【4月更文挑战第30天】本文将详细讨论Java 8的新特性,包括Lambda表达式、Stream API以及Optional类等,并探讨这些新特性如何改变了Java编程的实践。我们将通过实例代码展示这些新特性的用法,并分析其对提高代码可读性和编写效率的影响。
|
20天前
|
缓存 Java API
Java NIO和IO之间的区别
NIO(New IO),这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。在Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。
17 1
|
25天前
|
监控 Java 开发者
深入理解 Java 网络编程和 NIO
【4月更文挑战第19天】Java网络编程基于Socket,但NIO(非阻塞I/O)提升了效率和性能。NIO特点是非阻塞模式、选择器机制和缓冲区,适合高并发场景。使用NIO涉及通道、选择器和事件处理,优点是高并发、资源利用率和可扩展性,但复杂度、错误处理和性能调优是挑战。开发者应根据需求选择是否使用NIO,并深入理解其原理。
|
27天前
|
存储 监控 Java
浅谈Java NIO
浅谈Java NIO
7 0
|
28天前
|
消息中间件 存储 Java
【Java NIO】那NIO为什么速度快?
是这样的,在NIO零拷贝出现之前,一个I/O操作会将同一份数据进行多次拷贝。可以看下图,一次I/O操作对数据进行了四次复制,同时来伴随两次内核态和用户态的上下文切换,众所周知上下文切换是很耗费性能的操作。
29 1
【Java NIO】那NIO为什么速度快?