Java岗面试核心NIO有关知识总结

news2025/7/10 6:07:28
这篇文章主要是阅读了一些关于NIO的文章,对一些重要的部分进行了摘取总结。
 

BIO、NIO、AIO的不同

BIO:同步阻塞IO模式,线程发起IO请求后,一直阻塞IO,直到缓冲区数据就绪后,再进行下一步操作。
NIO:是同步非阻塞IO,线程发起IO请求后,立即返回。同步体现在selector仍然要去轮询判断channel是否准备好,非阻塞体现在这个过程中处理用户线程不会一直等待,可以去做其他的事情,但是要定时轮询IO缓存区数据是否准备好。
NIO主要有buffer、channel、selector三个组件,通过零拷贝的buffer获取数
AIO是异步非阻塞IO模型。在上述NIO实现中,需要用户线程定时轮询,去检查IO缓冲区数据是否准备就绪,占用应用程序线程资源,其实轮询也是阻塞的,它需要查询哪些IO就绪了。而真正的理想的异步非阻塞IO应该让内核系统完成,用户线程只需告诉内核,当缓冲区就绪后,通知我或者执行回调函数。
BIO存在的问题
在BIO模式中,socket.accept()、socket.read()、socket.write()三个主要函数都是同步阻塞的。当一个连接处理IO的时候,系统是阻塞的,要想处理多个连接,就要使用多线程。但是,当面对数万级别的连接时,传统的BIO模型就不行了,太消耗资源了。
NIO与IO的区别
NIO以块的方式处理数据,但是IO是以最基础的字节流的形式进行写入和读出。
NIO的通道是双向的,但是IO中的流是单向的。
NIO采用的是多路复用的IO模型,普通的IO用的就是阻塞的IO模型。

NIO的工作流程

1) 首先先创建ServerSocketChannel对象和真正处理数据的线程池。
2)然后给刚刚创建的ServerSocketChannel对象进行绑定一个对用的端口,然后设置为非阻塞。
3)然后创建Selector对象并打开,然后把这个ServerSocketChannel对象注册到Selector中,并设置好监听的事件,监听SelectionKey.OP_ACCEPT。
4)Selector对象死循环监听每一个Channel通道的事件,循环执行Selector.select()方法,轮询就绪的方法。
5)从Selector中获取所有的SelectorKey,如果SelectorKey是处于OP_ACCEPT状态,说明有新的客户端接入,调用ServerSocketChannel.accept接收新的客户端。
6)然后把这个接收的新客户端的Channel通道注册到ServerSocketChannel上,并且把之前的OP_ACCEPT状态改为SelectionKey.OP_READ读取事件状态,并且设置为非阻塞,然后把当前的这个SelectorKey给移除掉,说明这个事件完成了。
7)如果第五步的事件不是OP_ACCEPT,那就是OP_READ读取数据的事件状态。然后调用对应的机制。
 

不选择JAVA原生NIO编程的原因

NIO的类库和API繁琐,使用麻烦,你需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等。
需要具备其他的额外技能做铺垫,例如要熟悉Java多线程编程。
可靠性能力补齐,工作量和难度都非常大。比如说拆包闭包问题。
JDK NIO的BUG,例如臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU 100%。


为什么选择Netty

API简单,开发门槛低。
定制能力强,可以通过ChannelHandler对通信框架进行灵活的扩展。
成熟、稳定,Netty修复了已经发现的所有JDK NIO。
社区活跃,并且经历过大规模的商业应用考验。
 

Netty有什么特点

高并发。 Netty是一款基于NIO开发的网络通信框架,对比于BIO,它的并发性得到了很大的提高。
传输快。Netty的传输快是依赖于NIO的一个特性 零拷贝
封装好。Netty封装了NIO操作的很多细节,提供易于使用的API,开发门槛低。原生的NIO的API繁琐,使用麻烦。
可靠性。解决了一些原生NIO存在的问题,比如说空轮序,封包闭包问题。
 

Netty如何解决空轮询

  • 对Selector的select操作周期进行统计,每完成一次空的Select操作就进行一次计数。
  • 若在某个周期内连续发生N次空轮询,则触发epoll死循环bug。
  • 重建Selecto,判断是否是其他线程发起的重建请求,若不是则将原SocketChannel从旧的Selector上去除注册,重新注册到新的Selector上,并将原来的Selector关闭。

NIO组件之选择器的select

select操作的返回值不是已准备好的通道的总数,而是从上一个select()调用之后进入就绪态的通道的数量。之前的调用就绪的,并且在本次调用中仍就绪的通道不会被计入,而那些在前一次调用中已经就绪但是已经不再处于就绪状态的通道也不会被计入。
 

零拷贝

在传统的I/O操作中,每次都需要把内核空间的数据拷贝到用户空间中,这样挺浪费空间的,所以零拷贝的出现就是为了解决这个问题。
主要有两种方法: mmap+write 和 Sendfile
mmap+write
使用mmap+write方式替换原来的read+write方式,mmap是一种内存映射文件的方法,即将一个文件或者其他对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对应关系。
这样就可以省略掉原来内核Read缓冲区Copy数据到用户缓冲区,但是还是需要内核Read缓冲区将数据Copy到内核Socket缓冲区。
Sendfile
Sendfile是为了简化通过网络在两个通道内进行的数据传输过程。
它不仅减少了数据复制,还减少了上下文次数的切换。数据传送只发生在内核空间里,所以减少了一次上下文切换,但是还是存在一次Copy。
后来进行了改进,将Kernel Buffer中对应的数据描述信息(内存地址,偏移量)记录到相应的Socket缓冲区中,这样连内核空间中的一次CPU Copy也省掉了。
 

Netty的零拷贝具体体现

Netty零拷贝主要体现在三个方面。
Netty的接收和发送ByteBuffer采用DirtectByteBuffer,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。
Netty在操作多个Channel时,使用CompositeChannelBuffer,它并不会开辟新的内存并复制所有ChannelBuffer内容,而是直接保存了所有ChannelBuffer的引用,并在子ChannelBuffer里进行读写,实现了零拷贝。
Netty的文件传输采用了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel。

Netty工作流程服务端

1) 创建ServerBootStrap实例。
2)设置并绑定Reactor线程池:EventLoopGroup boss 和 worker,EventLoop就是处理所有注册到本线程Selector上面的Channel。
3)设置并绑定服务端的NioServerSocketChannel。
4)创建处理网络事件的ChannelPipeline和handler。
5)绑定并启动监听端口。
6)当轮询到准备就绪的channel后,由Reactor线程:NioEventLoop执行pipline中的方法,最终调度并执行channelHander。
 

客户端

1) 创建Bootstrap实例。
2)创建处理客户端连接Reactor线程组NioEventLoopGroup。
3)创建客户端连接的NioSocketChannel。
4)创建pipeline的channelHandler。
5)异步发起TCP连接并判断是否成功。

 

Java 自学免费加油站

Java基础语法-面向对象-集合-IO-线程与并发-异常-网络编程
java基础传送门: Java基础入门视频教程,零基础小白自学Java必备教程

​​

Java进阶
java进阶13天: Java13天进阶教程,深入学习Java编程核心思想
API:  Java基础教程2020新版JDK8日期API解析

​​

技术框架 Spring: Java进阶教程spring框架,深入浅出讲解细致
SpringMVC+ mybatis: Springmvc+Mybatis由浅入深全套视频教程
mybatis plus: MybatisPlus深入浅出教程,快速上手Mybatis-Plus
spring data: java进阶教程数据层全栈方案Spring Data高级应用

​​

分布式架构
Zookeeper+Dubbo: Dubbo快速入门,Java分布式框架必会的教程
Springcloud: SpringCloud从小白到精通教程
Skywalking: java基础教程全面的深入学习Skywalking
服务器中间件
Rabbitmq: RabbitMQ全套教程,RabbitMQ消息中间件到实战面试
Rocketmq: RocketMQ系统精讲,电商分布式消息中间件,硬核揭秘双十一
Kafka: Kafka深入浅出,快速玩转分布式发布订阅消息系统
Redis: Redis入门到精通,Java企业级解决方案必看
MongoDB: java必备基础教程-MongoDB基础入门到高级进阶
Apollo分布式: 轻松入门Apollo分布式配置中心-服务中间件
服务器技术
Tomcat: Java进阶教程Tomcat核心原理解析
容器技术
Docker: Docker容器化技术,从零学会Docker教程
Kubernetes: Kubernetes(K8S)超快速入门教程

​​

练手项目合集
1.传智健康项目 https://www.bilibili.com/video/BV1Bo4y117zVa
2.iHRM 人力资源管理系统 https://www.bilibili.com/video/BV18A411L7UXa
3.Java项目《 万信金融》企业级开发实战 https://www.bilibili.com/video/BV1Ub4y1f7rka
4.好客租房项目 https://www.bilibili.com/video/BV1sZ4y1F7PDa
5.品优购V1.3.1项目实战 https://www.bilibili.com/video/BV1mi4y1L7Hta
6.Java大型分布式微服务闪聚支付项目 https://www.bilibili.com/video/BV17v411V79c/a
7.Java集信达短信平台实战 https://www.bilibili.com/video/BV1J

​​

面试题:
深入解读阿里等一线大厂java面试必考HashMap技术点
Java面试热点问题,synchronized原理剖析与优化
Java面试热门内容精讲之——并发编程volatile
MySQL优化教程,超详细的MySQL数据库优化,Java面试热点必考问题

觉得有帮助可以抓紧收藏,说不定啥时候失效了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/5702.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringCloud基础知识【Hystrix熔断器】

SpringCloud基础知识【Hystrix熔断器】1. Hystrix概述2. Hystix-隔离2.1 线程池隔离2.2 信号量隔离2.3 Hystix隔离小结3. Hystix-降级3.1 服务提供方降级3.2 消费方降级3.3 Hystix降级小结4. Hystix-熔断4.1 代码演示4.1 熔断监控5. Hystix-限流1. Hystrix概述 Hystix&#xf…

基于概率距离削减法、蒙特卡洛削减法的风光场景不确定性削减(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

一文带你吃透数据库的约束,不做CRUD程序员

在SQL标准中,一共规定了6种不同的约束,包括非空约束,唯一约束和检查约束等,而在MySQL中是不支持检查约束的,所以这篇文章先对其余5种约束做一个详解和练习。 文章目录1. 约束的概念2. 约束的分类3. 非空约束4. 唯一约束…

.net 大型物流综合管理网络平台源码【免费分享】

淘源码:国内专业的免费源码下载平台 源码分享,需要源码学习可私信我! 一、源码描述 这是一款大型的物流综合管理网络平台源码,十分完整实用,便于调试,涵盖了物流综合管理的全面内容,该源码运行比…

单商户商城系统功能拆解30—营销中心—积分签到

单商户商城系统,也称为B2C自营电商模式单店商城系统。可以快速帮助个人、机构和企业搭建自己的私域交易线上商城。 单商户商城系统完美契合私域流量变现闭环交易使用。通常拥有丰富的营销玩法,例如拼团,秒杀,砍价,包邮…

【负荷预测】基于改进灰狼算法(IGWO)优化的LSSVM进行负荷预测(Matlab代码实现)

📝个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,…

IDEA 中Git 多次 Commit 合并为一次提交

一、背景 由于个人习惯的原因,喜欢一个功能分多次提交,导致很多提交比较零碎。 有时候经常需要将零碎的提交合并成一次,该怎么办? 可以使用 IDEA 自带的 Git 插件 将多次 Commit 合并成一次。 二、问题描述 如希望将第二次到第…

新品上市 | “电子表格软件”轻装上阵,企业报表用户的新选择

2022年11月14日,恰逢思迈特软件11周年的生日,我们更新了电子表格软件(Smartbi Spreadsheet),希望在一站式BI产品之外,更多的企业用户可以通过成熟、可控、小巧、灵活的报表工具,提升数据化管理的…

分击合进,锦江之星酒店与白玉兰酒店再领投资热潮

2022年11月11日,「山水画中游,暇享好时光」品牌品鉴会在广西桂林隆重召开。锦江酒店(中国区)旗下两大酒店品牌锦江之星酒店和白玉兰酒店携手亮相本次活动。 (品牌矩阵品鉴会活动现场) 后疫情时代&#xff…

JDBC编程的基本流程

文章目录1、创建数据源2、让代码和数据源建立连接3、操作数据库3.1 插入操作3.2 删除操作3.3 修改操作3.4 查找操作1、创建数据源 创建DataSource对象,这个对象描述了数据库服务器在哪,需要导入包javax.sql.DataSource DataSource databases new Mysq…

【第006篇】通过impdp命令导入dmp文件到Oracle11g数据库中

准备:按照dmp文件的账号密码,如 gwpc/gwpc 创建好表空间、用户等信息。 1、执行以下命令获取DATA_PUMP_DIR的值。 select * from dba_directories;2、将上图圈主的那个路径复制出来备用:/opt/oracle/app/admin/orcl/dpdump/ 3、将dmp文件放…

3.35 OrCAD中怎么产生Cadence Allegro的第一方网表?OrCAD软件输出Cadence Allegro第一方网表报错时应该怎么处理?

笔者电子信息专业硕士毕业,获得过多次电子设计大赛、大学生智能车、数学建模国奖,现就职于南京某半导体芯片公司,从事硬件研发,电路设计研究。对于学电子的小伙伴,深知入门的不易,特开次博客交流分享经验&a…

从0开始搭建ELK日志收集系统

Elasticsearch elasticsearch是一个高度可扩展全文搜索和分析引擎,基于Apache Lucene 构建,能对大容量的数据进行接近实时的存储、搜索和分析操作,可以处理大规模日志数据,比如Nginx、Tomcat、系统日志等功能。 Logstash 数据收…

一周侃 | 周末随笔

前言 明天又是周一了,感慨时间过得真快,2022年只差一个月就要过去了。大家年初定的目标实现了吗【狗头】 作为一个技术类博主,我平常除了看专业书籍和论文之外,很喜欢看一些闲书,比如时政类、经济类、历史人文类、科…

linux 进程通信 C程序案例

linux 进程通信 C程序案例 编写C程序完成&#xff1a;父进程创建两个子进程&#xff0c;每个进程都在屏幕上显示自己的进程ID号&#xff0c;并在第1个子进程中加载执行一条外部命令。 #include <stdio.h> #include <unistd.h> #include <sys/types.h> #inc…

看5G时代,“一键喊话”的大喇叭如何奏响基层治理最强音

“喂喂&#xff0c;各位居民朋友快下楼做核酸啦……” 通过广播传递最新政策、应急预警、疫情防控等信息&#xff0c;利用智能信息播报系统&#xff0c;打通基层宣讲“最后一公里”&#xff0c;已成为全国多地的常见景象。“多亏了它&#xff0c;需要紧急通知的时候&#xff0c…

Vue--》超详细教程——vue-cli脚手架的搭建与使用

目录 vue-cli vue-cli 的安装 (可能出现的问题及其解决方法) vue-cli 创建 Vue 项目 Vue项目中目录的构成 Vue项目的运行流程 Vue组件的使用 vue-cli vue-cli是Vue.js开发的标准工具。它简化了程序员基于webpack创建工程化的Vue项目的工程。其好处就是简省了程序员花费时…

Nacos——配置中心源码详解

Nacos——配置中心源码详解配置中心客户端主动获取客户端服务端客户端长轮询更新客户端1.入口2.配置文件分片处理3.配置文件处理4.本地配置文件与缓存数据的对比5.开启长轮询与服务端对比6.通知监听器7.监听回调处理服务端1.入口2.长轮询机制3.长轮询的延迟任务4.数据变更事件总…

【U8+】用友U8同一个账套使用了好多年,需要将以前年度进行分离、删除。

【问题需求】 用友U8一个账套使用了好多年了&#xff0c; 需要将以前年度进行删除&#xff0c; 但是在系统管理中&#xff0c;查看该账套只有一个年度账&#xff08;账套库&#xff09;。 例如&#xff1a; 图中002账套&#xff0c;是从2020年开始使用至2024年&#xff0c; 现在…

SpringBoot集成Spring Security——【认证流程】

一、认证流程 上图是 Spring Security 认证流程的一部分&#xff0c;下面的讲解以上图为依据。 &#xff08;1&#xff09; 用户发起表单登录请求后&#xff0c;首先进入 UsernamePasswordAuthenticationFilter&#xff1a; 在 UsernamePasswordAuthenticationFilter中根据用户…