NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。
NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。 NIO提供了与传统BIO模型中的 Socket
和 ServerSocket
相对应的 SocketChannel
和 ServerSocketChannel
两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发。
如果是在面试中回答这个问题,我觉得首先肯定要从 NIO 流是非阻塞 IO 而 IO 流是阻塞 IO 说起。然后,可以从 NIO 的3个核心组件/特性为 NIO 带来的一些改进来分析。如果,你把这些都回答上了我觉得你对于 NIO 就有了更为深入一点的认识,面试官问到你这个问题,你也能很轻松的回答上来了。
IO流是阻塞的,NIO流是不阻塞的。
Java NIO使我们可以进行非阻塞IO操作。比如说,单线程中从通道读取数据到buffer,同时可以继续做别的事情,当数据读取到buffer中后,线程再继续处理数据。写数据也是一样的。另外,非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。
Java IO的各种流是阻塞的。这意味着,当一个线程调用 read()
或 write()
时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了
IO 面向流(Stream oriented),而 NIO 面向缓冲区(Buffer oriented)。
Buffer是一个对象,它包含一些要写入或者要读出的数据。在NIO类库中加入Buffer对象,体现了新库与原I/O的一个重要区别。在面向流的I/O中·可以将数据直接写入或者将数据直接读到 Stream 对象中。虽然 Stream 中也有 Buffer 开头的扩展类,但只是流的包装类,还是从流读到缓冲区,而 NIO 却是直接读到 Buffer 中进行操作。
在NIO厍中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的; 在写入数据时,写入到缓冲区中。任何时候访问NIO中的数据,都是通过缓冲区进行操作。
最常用的缓冲区是 ByteBuffer,一个 ByteBuffer 提供了一组功能用于操作 byte 数组。除了ByteBuffer,还有其他的一些缓冲区,事实上,每一种Java基本类型(除了Boolean类型)都对应有一种缓冲区。
NIO 通过Channel(通道) 进行读写。
通道是双向的,可读也可写,而流的读写是单向的。无论读写,通道只能和Buffer交互。因为 Buffer,通道可以异步地读写。
NIO有选择器,而IO没有。
选择器用于使用单个线程处理多个通道。因此,它需要较少的线程来处理这些通道。线程之间的切换对于操作系统来说是昂贵的。 因此,为了提高系统效率选择器是有用的。
通常来说NIO中的所有IO都是从 Channel(通道) 开始的。
数据读取和写入操作图示:
NIO 包含下面几个核心的组件:
整个NIO体系包含的类远远不止这三个,只能说这三个是NIO体系的“核心API”。我们上面已经对这三个概念进行了基本的阐述,这里就不多做解释了。
代码示例出自闪电侠的博客,原地址如下:
https://www.jianshu.com/p/a4e03835921a
为什么大家都不愿意用 JDK 原生 NIO 进行开发呢?从上面的代码中大家都可以看出来,是真的难用!除了编程复杂、编程模型难之外,它还有以下让人诟病的问题:
Netty 的出现很大程度上改善了 JDK 原生 NIO 所存在的一些让人难以忍受的问题。
NIO Framework 是对 Java NIO 库的封装,将NIO的复杂度隐藏起来。有了它,人们可以方便地实现安全,高性能的Java网络应用程序。
snake 百万级别的分布式游戏服务器实时通讯 NIO 框架 数据库建议:Ignite/cockroach 发现服务:Zookeeper 1. messagecreator: 基于Netty的Java消息对象池,基于Netty零拷贝专为Netty做优化。 长时间运行,消息池和Netty总内存占用不超过2G,不用考虑GC。 2. zk-common Zookeeper基础服务发现组件。 3. log
问题内容: 我真的很麻烦:我想使用s和s 读取超过GB的巨大文件- 我发现的所有文档都暗示使用该方法映射文件相当简单。当然,由于所有Buffer方法都将int用于位置,限制和容量,因此限制为2GB,但是系统隐含的限制在那之下呢? 实际上,我遇到很多有关s 的问题!根本没有任何文件可以真正定义限制!因此- 如何在不获取异常的情况下将适合int-limit的文件安全地映射到一个或几个s中? 在尝试之前
主要内容:1 创建一个AsynchronousFileChannel,2 读取数据,3 通过Future读取数据,4 通过CompletionHandler读取数据,5 写数据,5 通过Future写入数据,6 通过CompletionHandler写入数据在Java 7中,它AsynchronousFileChannel已添加到Java NIO。这样AsynchronousFileChannel 就可以从文件中异步读取数据,或将数据异步写入文件。本教程将说明如何使用AsynchronousFi
主要内容:1 打开一个DatagramChannel,2 接收数据,3 发送数据,连接到特定地址Java NIO DatagramChannel是可以发送和接收UDP数据包的通道。由于UDP是无连接的网络协议,因此默认情况下,您不能仅从DatagramChannel其他通道读取和写入内容。相反,您发送和接收数据包。 1 打开一个DatagramChannel 这是打开方式DatagramChannel: 本示例打开一个DatagramChannel,它可以在UDP端口9999上接收数据包。
主要内容:1 ServerSocketChannel的介绍,2 打开一个ServerSocketChannel,3 关闭ServerSocketChannel,4 监听传入的连接,5 非阻塞模式1 ServerSocketChannel的介绍 Java NIO ServerSocketChannel是一个通道,可以侦听传入的TCP连接,就像ServerSocket在标准Java Networking中一样。该ServerSocketChannel班位于java.nio.channels包。 这是