JAVA的IO/NIO?

简介: JAVA的IO/NIO?

最传统的一种IO模式,即在读写的过程中发生阻塞,当用户发起IO请求后,内核会去查看数据是否就绪,如果没有就绪会等待线程就绪,而用户的请求线程就会进入阻塞状态,用户线程交出cpu控制权,当数据准备就绪,内核将会数据拷贝到用户线程,用户线程才会接触block状态。典型的IO模式例子就是data:socket.read()。

 

非阻塞IO则是在read的时候不需要等待,如果得到结果是false,则知道数据没有准备好,这时候则会继续发送read操作,一旦数据在buffe缓存里准备好了,这时候则可以获取到数据,然后返回。所以他的cpu控制权是不是释放的,会一直使用。

 

多路复用IO模式,是目前使用比较多的模式,上面说的非阻塞IO实际上就是多路复用IO,他的工作原理是:有一个线程不断的去轮询多个socket的状态,当socket真的发生了读写事件的时候,才会真正的调用read。这里是一个线程管理多个socket,而不是普通的NIO通过select()方法来read数据,当只有socket真的发生读写的时候,才会占用cpu资源去进行读操作。

另外为何多路复用比NIO效率更高,因为NIO是在不断的发送read查socket数据的,而多路复用,是把有数据的socket放在一个缓存区,轮询看哪个socket有数据,再去read()。不过多路复用IO是通过轮询的方式检测是否有事件大到达,并对事件逐一响应,当某个事件很大的时候,会影响后面事件的处理效率和事件轮播。

 

信号驱动IO,当用户发起一个IO请求的时候,会给对应的socket注册一个信号函数,然后用户线程会继续执行,当内核数据就绪时候会发送信号给用户线程,这时候用户线程会调用IO操作read读数据。

 

异步IO模式可以说是最理想的IO,当用户线程发起读操作的时候就可以去做其他事,完全不会发生阻塞,而内核的角度,java7提供的AsynchronousIO read之后,会立刻返回数据,说明数据已经返回,不会对用户线程block,然后内核数据准备完毕吧数据拷贝到用户线程,然后给用户线程发送一个信号,让他来读取数据,不需要用户线程发起IO操作,意思就是当数据准备完毕,用户线程读取数据之前,IO操作已经结束了。也就是说在异步中,IO的两个操作都不会阻塞,两个阶段都是由内核完成的。

 

JAVA NIO


Java的三大核心部分:Channel(通道),Buffer(缓存区),Selector。传统的IO基于字节和字符进行操作,而NIO则是通过Channel通道和buffer缓存来进行操作,数据总是通过通道发送到缓存,在从缓存读取到通道。Selector选择区用于监听多个通道事件(比如连接打开,数据到达),因此单个线程可以监听多个数据通道。(所以NIO是面向缓冲区的,IO是面向流的)

 

NIO的缓冲区是什么呢?java io面向的是流,意味着每次从流中读取一个或者多个字节,直到全部读取完,不会存在任何地方,此外他不能前后移动流中的数据,如果需要移动,则吧他们先存到缓冲区。NIO的缓冲和java 的io不同,数据先读取到缓冲区,可以在里面前后移动,这就增加了数据处理的灵活性,但是还需要检测缓冲区是否有您处理的数据,已经保证数据量过大的时候,不会覆盖缓冲区里的未处理数据。

 

NIO的非阻塞,io的各种流都是阻塞的,意味着当线程调用read后者write的时候,会进入阻塞状态,不能做任何其他事,直到数据完全查询或者写入。NIO的非阻塞模式使一个线程从通道发送请求数据,但他仅能得到目前缓存区已经有的数据,如果没有数据,则什么都没有获取到,也就不会阻塞影响线程做其他事。非阻塞写也是如此,当线程请求通道写入的时候,不需要等待写入完毕,则可以去做其他事。这就是为什么一个线程可以管理多个输入输出通道channel的原因。

 

Channel和io中的stream流差不多一个等级的。只不过stream是单向的,但是channel是双向的,可以读也可以写。主要实现有FileChannel、DatagramChannel、socketChannel、ServerSocketChannel。

 

Buffer缓冲区实际就是一个容器,一个连续的数组,channel提供从文件网络读取数据的渠道,但是读取和写入都必须经过buffer。    Buffer是一个抽象类,常用的有byteBuffer,intBffer等。他的流程就是数据读的时候先进入buffer然后到通道里,写数据的时候也是先从通道到buffer然后到server。

 

Selector是NIO的一个核心类,selector可以检测多个注册通道是否有事件发生,以便获取事件然后针对每个事件进行响应处理。这样一来只需要单个线程就能处理多个通道,当真的监听到读写时间,才会调用函数,减少了系统的开销,不必为每个连接都创建一个线程,不用维护线程,避免上下文切换。

相关文章
|
17天前
|
Java Unix Windows
|
2天前
|
Java 开发者
Java一分钟之-Java IO流:文件读写基础
【5月更文挑战第10天】本文介绍了Java IO流在文件读写中的应用,包括`FileInputStream`和`FileOutputStream`用于字节流操作,`BufferedReader`和`PrintWriter`用于字符流。通过代码示例展示了如何读取和写入文件,强调了常见问题如未关闭流、文件路径、编码、权限和异常处理,并提供了追加写入与读取的示例。理解这些基础知识和注意事项能帮助开发者编写更可靠的程序。
9 0
|
6天前
|
存储 缓存 Java
Java IO 流详解
Java IO 流详解
16 1
|
10天前
|
存储 Java
Java的`java.io`包包含多种输入输出类
Java的`java.io`包包含多种输入输出类。此示例展示如何使用`FileInputStream`从`input.txt`读取数据。首先创建`FileInputStream`对象,接着分配一个`byte`数组存储流中的数据。通过`read()`方法读取数据,然后将字节数组转换为字符串打印。最后关闭输入流释放资源。`InputStream`是抽象类,此处使用其子类`FileInputStream`。其他子类如`ByteArrayInputStream`、`ObjectInputStream`和`BufferedInputStream`各有特定用途。
21 1
|
11天前
|
存储 Java
java IO接口(Input)用法
【5月更文挑战第1天】Java的`java.io`包包含多种输入输出类。此示例展示了如何使用`FileInputStream`从`input.txt`读取数据。首先创建`FileInputStream`对象,接着创建一个字节数组存储读取的数据,调用`read()`方法将文件内容填充至数组。然后将字节数组转换为字符串并打印,最后关闭输入流。注意,`InputStream`是抽象类,此处使用其子类`FileInputStream`。其他子类如`ByteArrayInputStream`、`ObjectInputStream`和`BufferedInputStream`各有特定用途。
21 2
|
13天前
|
存储 Java Linux
【Java EE】 文件IO的使用以及流操作
【Java EE】 文件IO的使用以及流操作
|
18天前
|
存储 Java 数据库
[Java 基础面试题] IO相关
[Java 基础面试题] IO相关
|
18天前
|
缓存 Java API
Java NIO和IO之间的区别
NIO(New IO),这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。在Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。
16 1
|
21天前
|
Java
Java基础教程(12)-Java中的IO流
【4月更文挑战第12天】Java IO涉及输入输出,包括从外部读取数据到内存(如文件、网络)和从内存输出到外部。流是信息传输的抽象,分为字节流和字符流。字节流处理二进制数据,如InputStream和OutputStream,而字符流处理Unicode字符,如Reader和Writer。File对象用于文件和目录操作,Path对象简化了路径处理。ZipInputStream和ZipOutputStream则用于读写zip文件。
|
23天前
|
监控 Java 开发者
深入理解 Java 网络编程和 NIO
【4月更文挑战第19天】Java网络编程基于Socket,但NIO(非阻塞I/O)提升了效率和性能。NIO特点是非阻塞模式、选择器机制和缓冲区,适合高并发场景。使用NIO涉及通道、选择器和事件处理,优点是高并发、资源利用率和可扩展性,但复杂度、错误处理和性能调优是挑战。开发者应根据需求选择是否使用NIO,并深入理解其原理。