10个最高频的Java NIO面试题剖析。

?

  首先我们分别画图来看看,BIO、NIO、AIO,分它是什么?

BIO:传统的网络通信模型是BIO,同步阻塞IO

它实际上是创建ServerSocket的服务器,然后客户端使用Socket连接到ServerSocket服务器。 ServerSocket接收连接请求以创建Socket和与Socket通信的线程。

然后客户端和服务器执行阻塞通信,客户端发送请求,服务器Socket处理并返回响应。

在响应返回之前,客户端被阻塞等待,并且门无法执行任何操作。

这种方法的缺点是:每次客户端访问时,都需要在服务器上创建一个线程来为这个客户端提供服务

当如此大量的客户端出现时,服务器上的线程数可能达到数千甚至数万,这可能导致服务器过载过高,最终崩溃将会死亡。

BIO模型图:

受体:

传统IO模型网络服务的设计模式中有两种经典的设计模式:一种是多线程的,另一种是依赖线程池进行处理。

如果是基于多线程模式,那就是这样一种模式,这也是Acceptor线程模型。

NIO:

NIO是基于Reactor模型的同步非阻塞IO。

实际上,它相当于一个处理大量客户端请求的线程,通过一个线程轮询大量通道,每次获取一批带有事件的通道,然后为每个请求启动一个线程处理。

这里的核心是非阻塞的。在该选择器上,线程可以连续轮询通道。所有客户端请求都不会阻止,并且会直接进入。最重要的是等待队列。

这里优化BIO的核心是客户端始终没有数据交互。没有必要死于一个线程,所以客户端选择让线程休息,只有客户端有相应的操作。仅在通知发起时。创建一个线程来处理请求。

NIO:模型地图

反应堆型号:

AIO

AIO:基于Proactor模型的异步非阻塞IO。

每个连接发送请求都会绑定到一个Buffer,然后通知操作系统完成异步读取,此时可以做其他事情

操作系统完成读取后,它将调用您的界面并为您提供操作系统异步读取的数据。此时,您可以获取要处理的数据并将数据写回论坛

在写回的过程中,同样是给操作系统一个Buffer,让操作系统完成写操作,然后写它来通知你。

这两个进程都有缓冲区,缓冲区读取和写入数据。

这里的主要区别是,在将数据写入缓冲区后,它将保持未选中状态,其余部分将留给操作系统完成。

操作系统回写数据也是如此。将其写入缓冲区并通知客户端在写入后读取数据。

AIO:模型地图

在谈到BIO,NIO和AIO之间的区别之后,现在我们将这三种模型中的一些结合起来解决同步和阻塞问题。

同步阻止

为什么BIO会同步阻塞?

实际上,这不是关于网络通信模型,而是针对磁盘文件的读写IO操作。

由于BIO流读取和写入文件(例如FileInputStrem),因此意味着您发起IO请求并直接死亡。卡在那里,你必须等待IO返回。

同步非阻塞:

为什么NIO同步同步非阻塞?

因为无论有多少客户端可以访问服务器,客户端访问都不会花费线程,只创建连接然后注册到选择器,因此您可以执行其他您想要执行的操作。 p>

选择器线程不断轮询所有套接字连接,并在检测到事件时通知您,然后启动线程来处理请求。此过程是非阻塞的。

但是在此过程的过程中,您仍然必须读取数据,处理它,然后返回它。这是一个同步过程。

异步非阻塞

为什么AIO异步且无阻塞?

通过AIO启动文件IO操作后,您只需返回执行其他操作,然后您就不必担心了。操作系统完成IO后,告诉你说好了

当您根据AIO的api读取和写入文件时,当您提出请求时,其余的将被移交给操作系统。

读写完成后,操作系统会来回调整您的界面,告诉您操作已完成

在此期间无需等待,无需轮询以确定操作系统的状态。你可以做其他事情。

同步意味着您必须主动轮询操作系统。异步是通知您的操作系统。因此,AIO是异步且无阻塞的。

详细解释了NIO核心组件

首先学习NIO以找出一些相关的概念,NIO通信的相关组件是什么,相应的角色是什么,链接是什么?

多路复用机制实现了选择器

首先,我们来看看传统的Socket网络通信模型。

传统插座通信原理图

为什么传统插座不支持大规模连接?

每次客户端访问时,都需要在服务器上创建一个线程来为客户端提供服务。

这可能导致大量客户端,服务器上的线程数可能达到数千甚至数万,数十万,这将导致服务器端程序加载过高,不堪重负,最终导致系统崩溃。

然后看看NIO是如何基于Selector多路复用机制支持的大规模连接。

NIO原理图

多路复用机制如何支持大规模连接?

NIO的线程模型不需要为Socket启动的每个连接创建一个线程。它可以使用选择器来复用和监听N个多个信道,无论是否有请求,请求是相应的连接请求还是发送数据的请求。

这基于操作系统的基础Select通知机制。选择器连续轮询多个通道,从而避免创建多个线程。

仅当存在对Channel的相应请求时才创建线程。可以说1000个请求,只有100个请求有数据交互。

此时,服务器可以提供10个线程来处理这些请求。这样您就可以避免创建大量线程。

NIO如何通过Buffer

缓冲数据

什么是NIO中的缓冲区?

学习NIO,首先要做的是理解所谓的缓冲区缓冲区,这是NIO核心的一部分。

通常,如果要通过NIO将数据写入文件或网络,或者从文件和网络读取数据,则需要使用缓冲区缓冲区。 Buffer的使用通常包括以下步骤:

将数据写入Buffer,调用flip()方法,并从Buffer中读取数据。调用clear()方法或compact()方法。

缓冲区中相应的位置,标记,容量和限制是多少?

容量:缓冲区容量的大小,即包含在其中的数据的大小。

限制:对此索引无法读取的缓冲区缓冲区的限制。

Position:表示数组中可以开始读写的索引,不能大于limit。

马克:就像一个路标。在某个位置设置标记时,可以在此时设置标记

对reset()方法的后续调用将位置重置为此时设置的标记。将位置或限制调整为小于标记的值时,请丢弃标记

如果使用Direct模式创建的Buffer,它将减少中间缓冲区并直接使用DirectorBuffer来存储数据。

如何通过Channel和FileChannel读取缓冲区数据到磁盘

NIO中的频道是什么?

频道是NIO中的数据频道,类似于流媒体,但有些不同

通道可以从通道读取数据并将数据写入通道,但流的读取和写入通常是单向的。

可以异步读取和写入通道。通道中的数据必须始终读入缓冲区或从缓冲区写入通道。

FileChannel的作用是什么?

缓冲区有不同的类型,有几种类型的频道。

FileChannel

DatagramChannel

的SocketChannel

的ServerSocketChannel

这些通道涵盖UDP和TCP网络IO以及文件IO。 FileChannel是与文件IO对应的管道,在读取文件时使用。

让我们给出一个简单的NIO实现来读取文件的演示代码

NIOServer和客户端代码示例

最后,给大家一个NIO客户端和服务器示例代码,只需感受NIO通信的方式。

NIO通信客户端

NIO通信服务器

摘要:

BIO,NIO,AIO各自的特点

什么是同步阻塞,同步非阻塞,异步非阻塞

为什么NIO可以应对大量的支持请求

NIO相关组件的原理

一个简单的NIO通信案例

本文刚才介绍了网络通信的一些原理,并应该对采访进行解释。

NIO通信实际上有很多东西,中间件开发过程中的使用频率仍然很高,并且有机会与您分享。

最后,分享一本采访书[Java核心知识点整理]涵盖JVM,锁定,高并发,反射,Spring原理,微服务,Zookeeper,数据库,数据结构等“,以及Java208面试问题(带答案)加入我的粉丝群(Java Fill Road:)并免费获得!掌握这些知识点,你可以在面试中赢得很多候选人,获得9999分。机会留给准备好的人,只有充分的准备,可以使自己在候选人中脱颖而出。