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

相关文章
|
2天前
|
Java Unix Windows
|
2天前
|
监控 Java
Java一分钟之-NIO:非阻塞IO操作
【5月更文挑战第14天】Java的NIO(New IO)解决了传统BIO在高并发下的低效问题,通过非阻塞方式提高性能。NIO涉及复杂的选择器和缓冲区管理,易出现线程、内存和中断处理的误区。要避免这些问题,可以使用如Netty的NIO库,谨慎设计并发策略,并建立标准异常处理。示例展示了简单NIO服务器,接收连接并发送欢迎消息。理解NIO工作原理和最佳实践,有助于构建高效网络应用。
8 2
|
2天前
|
Java 开发者
Java一分钟之-Java IO流:文件读写基础
【5月更文挑战第10天】本文介绍了Java IO流在文件读写中的应用,包括`FileInputStream`和`FileOutputStream`用于字节流操作,`BufferedReader`和`PrintWriter`用于字符流。通过代码示例展示了如何读取和写入文件,强调了常见问题如未关闭流、文件路径、编码、权限和异常处理,并提供了追加写入与读取的示例。理解这些基础知识和注意事项能帮助开发者编写更可靠的程序。
17 0
|
2天前
|
存储 缓存 Java
Java IO 流详解
Java IO 流详解
18 1
|
2天前
|
存储 Java
Java的`java.io`包包含多种输入输出类
【5月更文挑战第2天】Java的`java.io`包包含多种输入输出类。此示例展示如何使用`FileInputStream`从`input.txt`读取数据。首先创建`FileInputStream`对象,接着分配一个`byte`数组存储流中的数据。通过`read()`方法读取数据,然后将字节数组转换为字符串打印。最后关闭输入流释放资源。`InputStream`是抽象类,此处使用其子类`FileInputStream`。其他子类如`ByteArrayInputStream`、`ObjectInputStream`和`BufferedInputStream`各有特定用途。
34 1
|
2天前
|
存储 Java
java IO接口(Input)用法
【5月更文挑战第1天】Java的`java.io`包包含多种输入输出类。此示例展示了如何使用`FileInputStream`从`input.txt`读取数据。首先创建`FileInputStream`对象,接着创建一个字节数组存储读取的数据,调用`read()`方法将文件内容填充至数组。然后将字节数组转换为字符串并打印,最后关闭输入流。注意,`InputStream`是抽象类,此处使用其子类`FileInputStream`。其他子类如`ByteArrayInputStream`、`ObjectInputStream`和`BufferedInputStream`各有特定用途。
22 2
|
2天前
|
存储 Java Linux
【Java EE】 文件IO的使用以及流操作
【Java EE】 文件IO的使用以及流操作
|
2天前
|
存储 Java 数据库
[Java 基础面试题] IO相关
[Java 基础面试题] IO相关
|
2天前
|
缓存 Java API
Java NIO和IO之间的区别
NIO(New IO),这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。在Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。
17 1
|
10月前
|
Java
Java NIO系列教程三
​ 今天主要给大家介绍的是Buffer的基本使用这个也是NIO里面最总要的概率之一,里面的操作也是有一些复杂的同时也是需要大家必须要重点掌握的知识点,同时也介绍了一下Selector的用法下一篇文章我们将为大家介绍Pipe管道以及FileLock文件锁这也是NIO里面最后的一分部内容了。
81 0