文章目录
- IO常见面试题
- IO分类
- 字符流-字节流-缓冲区
- 同步阻塞IO/BIO
- 同步非阻塞IO/NIO
-
- [java NIO由几个核心部门:缓存Buffers;通道Channels;选择器Selectors。](#java NIO由几个核心部门:缓存Buffers;通道Channels;选择器Selectors。)
- 异步非阻塞IO/AIO
IO常见面试题
java中io流分为几种
- 按照流的流向可分为输入流与输出流
- 按照操作单元分可分为字节流和字符流
BIO,NIO,AIO有什么区别
- BIO:同步阻塞io:数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不多的情况下,这种模型就比较不错。
- NIO:同步非阻塞io:它支持面向缓冲,基于通道的I/O操作方法。
- AIO(NIO2):异步非阻塞io:高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发
IO分类
字符流-字节流-缓冲区
字节流、字符流和转换流之间的关系
- 字节流:读取字节到内存或将字节写入硬盘文件中。
- 字符流:将字节转换为字符(读入)或将字符转换为字节(写出)。
- 转换流:将字节按照指定的编码格式转换为字符(读入),或将字符按照指定的编码格式转换为字节(写出)。
字节字符得区别
- 字节流是最基本的,所有的InputStream和OutputStream的子类都是,主要用在处理二进制数据,它是按字节来处理的
- 字符流的概念,它是按虚拟机的encode来处理,也就是要进行字符集的转化。
缓冲区
-
可以简单地理解为一段内存区域,某些情况下,如果一个程序频繁地操作一个资源(如文件或数据库),则性能会很低,此时为了提升性能,就可以将一部分数据暂时读入到内存的一块区域之中,以后直接从此区域中读取数据即可,因为读取内存速度会比较快,这样可以提升程序的性能。
-
字符都是在内存中形成的,在输出前会将所有的内容暂时保存在内存之中,所以使用了缓冲区暂存数据。
对于 Java 字符流的操作都是在缓冲区操作的,所以如果我们想在字符流操作中主动将缓冲区刷新到文件则可以使用 flush() 方法操作。
同步阻塞IO/BIO
- 用户需要等待read将socket中的数据读取到buffer后,才继续处理接收的数据。整个IO请求的过程中,用户线程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够。
- 基本通信过程是每次client请求过来时server会启动一个线程进行通信,这种通信模型最大的缺点就是:一连接一线程的模型导致服务端无法承受大量客户端的并发连接。从而导致服务器线程暴增,性能急剧下降,甚至宕机。
同步非阻塞IO/NIO
- 采用一个线程来管理多个客户端的连接请求,这样能够确保在连接过程中不会被阻塞,在将建立好的连接分配给对应的处理线程
java NIO由几个核心部门:缓存Buffers;通道Channels;选择器Selectors。
缓冲区(buffer):
缓冲区实际上是一个容器对象,更直接的说,其实就是一个数组,在NIO 库中,所有数据都是用缓冲区处理的。
使用Buffer读写数据一般遵循以下四个步骤:
1:写入数据到Buffer: 直接将数据写入buffer
在缓冲区中,最重要的属性有下面三个,它们一起合作完成对缓冲区内部状态的变化跟踪:
- position:指定了下一个将要被写入或者读取的元素索引,它的值由get()/put()方法自动更新,在新创建一个Buffer 对象时,position 被初始化为0。
- limit:指定还有多少数据需要取出(在从缓冲区写入通道时),或者还有多少空间可以放入数据(在从通道读入缓冲区时)。
- capacity:指定了可以存储在缓冲区中的最大数据容量,实际上,它指定了底层数组的大小,或者至少是指定了准许我们使用的底层数组的容量。
2:调用flip()方法:通过flip()将buffer从写模式切换到读模式
3:从Buffer中读取数据:
4:调用clear()方法或者compact()方法:
- clear()方法会清空整个缓冲区。
- compact()方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。
通道(channel):
- 是一个通道,通过它读写 Buffer 中的数据。
- Java NIO中几个最重要的通道的实现
1:FileChannel:
从文件中读写数据
2:DatagramChannel:
能通过UDP读写网络中的数据
3:SocketChannel:
能通过TCP读写网络中的数据
4:ServerSocketChannel:
可以监听新进来的TCP连接,对每一个新进来的连接都会创建一个SocketChannel
多路复用器(selector):
多路复用器,Selector 不断轮询注册在其上的 Channel,如果某个 Channel 有新的 TCP 链接接入、读和写事件,这个 Channel 就处于就绪状态,会被 Selector 轮组出来,通过SelectionKey() 可以获取就绪 Channel 的集合,进行后续的 IO。
异步非阻塞IO/AIO
AIO(Asynchronous I/O)是一种异步非阻塞的 I/O 模型,其实现原理如下:
-
操作系统支持:
AIO 需要操作系统提供对异步 I/O 的支持,通常通过操作系统提供的异步 I/O 接口来实现。
-
事件驱动:
AIO 通过事件驱动的方式来处理 I/O 操作。当应用程序发起一个异步 I/O 请求后,操作系统会立即返回,而不会阻塞当前线程。
-
回调函数:
在异步 I/O 操作完成后,操作系统会通知应用程序,应用程序可以注册一个回调函数(Callback),当 I/O 操作完成时,操作系统会调用这个回调函数来处理完成的结果。
-
内核态处理:
异步 I/O 操作通常由操作系统的内核来处理,内核会负责实际的 I/O 操作,而应用程序可以继续执行其他任务,不会被阻塞。
-
适用场景:
AIO 适用于需要处理大量并发连接且每个连接的 I/O 操作耗时较长的场景,例如网络编程中的高性能服务器。
总的来说,AIO 通过事件驱动和回调函数的方式实现了异步非阻塞的 I/O 操作,提高了系统的并发能力和性能。