Java中NIO和IO区别和适用场景

本文对比了NIO和传统IO的主要区别,包括面向缓冲区而非流、非阻塞特性及适用场景。NIO通过引入非阻塞I/O、选择器等机制提高了数据处理效率。
NIO是为了弥补IO操作的不足而诞生的,NIO的一些新特性有:非阻塞I/O,选择器,缓冲以及管道。管道(Channel),缓冲(Buffer) ,选择器( Selector)是其主要特征。

概念解释:

Channel——管道实际上就像传统IO中的流,到任何目的地(或来自任何地方)的所有数据都必须通过一个 Channel 对象。一个 Buffer 实质上是一个容器对象。

Selector——选择器用于监听多个管道的事件,使用传统的阻塞IO时我们可以方便的知道什么时候可以进行读写,而使用非阻塞通道,我们需要一些方法来知道什么时候通道准备好了,选择器正是为这个需要而诞生的。

NIO和传统的IO有什么区别呢?

1,IO是面向流的,NIO是面向块(缓冲区)的。

        IO面向流的操作一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。,导致了数据的读取和写入效率不佳;

        NIO面向块的操作在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多,同时数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。通俗来说,NIO采取了“预读”的方式,当你读取某一部分数据时,他就会猜测你下一步可能会读取的数据而预先缓冲下来。

2,IO是阻塞的,NIO是非阻塞的。

        对于传统的IO,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。

        而对于NIO,使用一个线程发送读取数据请求,没有得到响应之前,线程是空闲的,此时线程可以去执行别的任务,而不是像IO中那样只能等待响应完成。

3,NIO和IO适用场景

        NIO是为弥补传统IO的不足而诞生的,但是尺有所短寸有所长,NIO也有缺点,因为NIO是面向缓冲区的操作,每一次的数据处理都是对缓冲区进行的,那么就会有一个问题,在数据处理之前必须要判断缓冲区的数据是否完整或者已经读取完毕,如果没有,假设数据只读取了一部分,那么对不完整的数据处理没有任何意义。所以每次数据处理之前都要检测缓冲区数据。

那么NIO和IO各适用的场景是什么呢?

        如果需要管理同时打开的成千上万个连接,这些连接每次只是发送少量的数据,例如聊天服务器,这时候用NIO处理数据可能是个很好的选择。

        而如果只有少量的连接,而这些连接每次要发送大量的数据,这时候传统的IO更合适。使用哪种处理数据,需要在数据的响应等待时间和检查缓冲区数据的时间上作比较来权衡选择。

4,通俗解释

最后,对于NIO和传统IO,有一个网友讲的生动的例子:

以前的流总是堵塞的,一个线程只要对它进行操作,其它操作就会被堵塞,也就相当于水管没有阀门,你伸手接水的时候,不管水到了没有,你就都只能耗在接水(流)上。

nio的Channel的加入,相当于增加了水龙头(有阀门),虽然一个时刻也只能接一个水管的水,但依赖轮换策略,在水量不大的时候,各个水管里流出来的水,都可以得到妥

善接纳,这个关键之处就是增加了一个接水工,也就是Selector,他负责协调,也就是看哪根水管有水了的话,在当前水管的水接到一定程度的时候,就切换一下:临时关上当前水龙头,试着打开另一个水龙头(看看有没有水)。

当其他人需要用水的时候,不是直接去接水,而是事前提了一个水桶给接水工,这个水桶就是Buffer。也就是,其他人虽然也可能要等,但不会在现场等,而是回家等,可以做其它事去,水接满了,接水工会通知他们。

这其实也是非常接近当前社会分工细化的现实,也是统分利用现有资源达到并发效果的一种很经济的手段,而不是动不动就来个并行处理,虽然那样是最简单的,但也是最浪费资源的方式。


转载自:http://www.php.cn/java-article-361228.html

### 三层结构详解:Java NIOIO区别 #### 面向流与面向缓冲 Java IO 是面向流的,意味着每次从流中读取一个或多个字节,无法在数据流中前后移动。而 Java NIO 是面向缓冲的,数据首先被读取到缓冲区中,之后可以在缓冲区中灵活地操作数据。这种机制使得 NIO 在处理大数据量时效率更高,因为可以减少系统调用上下文切换的次数[^1]。 #### 阻塞与非阻塞 IO Java IO 的操作是阻塞的,即当调用 `read()` 或 `write()` 方法时,线程会一直阻塞,直到数据读取或写入完成。而 Java NIO 支持非阻塞模式,线程可以在没有数据就绪的情况下继续执行其他任务,从而提高并发性能。这种特性使得 NIO 更适合高并发的网络编程场景[^1]。 #### 选择器机制 Java NIO 引入了选择器(Selector)机制,它允许单个线程管理多个通道(Channel)。通过选择器,可以监听多个通道的事件(如连接、读就绪等),并在事件触发时进行相应的处理。这种机制显著减少了线程的数量,降低了线程管理上下文切换的开销,适用于大规模并发连接的场景[^1]。 #### 示例代码:NIO 文件操作 以下是一个使用 Java NIO 进行文件操作的示例代码,展示了如何通过 `FileChannel` `ByteBuffer` 实现高效的文件读写操作。 ```java import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class FileChannelExample { public static void main(String[] args) { try (RandomAccessFile file = new RandomAccessFile("example.txt", "rw"); FileChannel fileChannel = file.getChannel()) { // 创建Buffer并写入数据 ByteBuffer buffer = ByteBuffer.allocate(1024); String data = "Hello, FileChannel!"; buffer.put(data.getBytes()); // 准备Buffer进行读操作 buffer.flip(); fileChannel.write(buffer); // 清空Buffer以便再次写入 buffer.clear(); // 设置Channel位置并读取数据 fileChannel.position(0); int bytesRead = fileChannel.read(buffer); System.out.println("读取 " + bytesRead + " 字节"); // 准备Buffer进行读操作 buffer.flip(); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } } catch (Exception e) { e.printStackTrace(); } } } ``` #### 性能与适用场景 Java NIO 的设计初衷是为了提升 IO 操作的性能,尤其是在处理大量并发连接时。由于 NIO 提供了缓冲区非阻塞机制,它更适合需要高性能高并发的应用场景,如网络服务器客户端。而传统的 Java IO 更适合简单的文件操作少量连接的场景,因为其编程模型更为直观简单[^2]。 #### 扩展框架:Netty Netty 是一个基于 Java NIO 的高性能网络编程框架,广泛用于构建高性能的网络服务器客户端。Netty 提供了丰富的功能,如异步事件驱动的网络应用支持,简化了 NIO 编程的复杂性,并提高了开发效率应用性能。通过 Netty,开发者可以更容易地利用 NIO 的优势,构建稳定、高效的网络应用。 #### 相关问题 1. Java NIO 中的缓冲区是如何工作的? 2. 如何在实际项目中使用 Netty 框架? 3. Java IO NIO 在网络编程中的具体应用场景有哪些? 4. 非阻塞 IO 在高并发场景下的优势体现在哪些方面? 5. 如何选择适合的 IO 模型来优化应用程序性能?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值