当前位置: 首页 > news >正文

BIO到NIO、多路复用器, 从理论到实践, 结合实际案例对比各自效率与特点(下)

文章目录

    • 多路复用器简介
    • 多路复用器的两个阶段
    • Java中的多路复用器封装
    • 测试代码
    • 压测结果
    • 总结

本篇文章是BIO到NIO、多路复用器, 从理论到实践, 结合实际案例对比各自效率与特点(上)的下一篇, 如果没有看的小伙伴, 可以先看下, 不然可能会不连贯.

多路复用器简介

多路复用器是对于传统NIO的优化, 解决了传统NIO无法直接获取所有所有连接的状态, 需要挨个遍历所有连接查看是否准备就绪的问题, 这种方式会涉及到很多次系统调用, 用户态和内核态的切换,效率不高.

那多路复用器是怎样优化的呢?
首先要明白 多路的路是谁-------->其实就是每个IO连接

每个路有没有数据谁知道呢-------->内核知道, 那既然内核自己知道某一时刻有哪些连接是有连接的, 是不是我们直接调用对应功能方法即可, 所以这里就有个多路复用器, 你调用这个多路复用器, 它就会给你返回所有的路的IO状态.

这个就可以通过一次系统调用,获取所有连接的IO状态的结果集
然后程序自己对有状态的(准备好的)连接进行读写,这样才是高性能

这里注意,多说一句, 只要程序自己读写数据, 你的IO模型就是同步的
在这里插入图片描述

多路复用器的两个阶段

多路复用器有两个阶段, 或者说是内核的两类实现, 这两类实现的最终目的都是一样的, 就是帮你返回所有IO连接的IO状态(是否可读), 但是实现细节有些许差别, 可以理解为epoll是select poll的升级版.

这里还是再提示下, 以下的两种实现讲的操作系统中的实现, 并不是Java中的方法.

  • select poll
    需要把所有IO连接存到一个集合中, 把这个集合传递拷贝给内核, 也就是调用select或者poll, 内核会把集合中准备就绪的连接给个特殊标识, 然后返回.
    这样程序就可以直接知道哪些连接是有状态的, 从而直接进行读取数据
    弊端:
    假如有1w个连接, 每次都需要把这个1w个连接拷贝给内核, 这个拷贝就是损耗点, 每次需要重复拷贝数据给内核.

  • epoll
    正是因为select, poll 有自身的弊端, 这才催生了epoll.
    优化
    以空间换时间, 开辟了内核空间, 缓存了应用程序的连接信息. 这样就不需要重复的拷贝数据.无损耗才是高性能.

    实现步骤
    1. 在一个linux机器上, 有很多的应用程序, 所以一个应用程序想要使用epoll的话, 首先需要在内核中 开辟空间------对应epoll_create系统调用
    2. 然后当连接创建后, 把这个连接加入到该空间------对应epoll_ctl(add)系统调用
    3. 然后才是进行询问, 看看有哪些IO连接准备就绪------对应epoll_wait系统调用

Java中的多路复用器封装

在java.nio的包下,封装了对于多路复用的实习和使用,也就是Selector类

Java中的Seletor底层用的是哪种实现? select poll 还是epoll?
Java其实会在运行的时候会动态的决定使用哪种实现, 因为它会调用固定的方法去启动多路复用器,即Selector.open, 你的程序可能跑在不同的内核之上, jdk会优先选择好的epoll, 但是如果没有epoll这个多路复用器的话,只有select或者poll, 也是可以正常运行的

主要使用方法介绍:
这里有三个主要的方法, 不管底层使用的是哪种实现, 都会调用这三个方法, 但是根据不同实现, 具体做的事情又不一样,区别如下:

  1. Selector.open
    启动多路复用器, 优先选择epoll, 没有的话选择select或者poll.
    如果是epoll的话, 需要在内核中开辟空间, 即调用epoll_create.
  2. register
    select、poll: 会在jvm里建一个数组, 把每个连接对应的文件描述符(fd4)都放进去.
    epoll: 则相当于调用内核方法epoll_ctl(add), 将该连接加入到内核空间, 直接由内核管理.
  3. select
    select、poll: 则会将jvm中的数组传给内核, 即调用select(fd4)或者poll(fd4)
    epoll: 相当于直接调用内核方法epol_wait, 直接询问内核

测试代码

服务端

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;/*** @ClassName:     * @Description:(描述这个类的作用)   * @author: * @date:        *   */  
public class SelectorTest {private static ServerSocketChannel server=null;private static Selector selector;static int port=9090;static int count=5000;static long startTime;public static void initServer(){try {server = ServerSocketChannel.open();server.configureBlocking(false);server.bind(new InetSocketAddress(port));//这里会在编译期间自动选择 多路复用器的 实现//可能为select poll 也可能为epollselector = Selector.open();server.register(selector, SelectionKey.OP_ACCEPT);} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {initServer();System.out.println("服务器启动了......");startTime = System.currentTimeMillis();try {flag:while (true){//select相当于询问内核有无数据可读取 或者 有无连接可建立//里面传入的参数是超时时间,传入0代表阻塞,一直等待有人建立连接或发送数据//如果传入的>0, 比如200, 则会最多等待200毫秒,有没有都会返回一个结果while(selector.select(0)>0){//从多路复用器中取出所有有效的keySet<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while(iterator.hasNext()){SelectionKey key = iterator.next();//获取之后要进行移除,否则会重复获取iterator.remove();//有新连接可建立if(key.isAcceptable()){acceptHander(key);//可以进行读取}else if(key.isReadable()){readHander(key);}}if(count <= 0){System.out.println("处理5000个连接用时:"+(System.currentTimeMillis()-startTime)/1000+"s");server.close();selector.close();break flag;}}}}catch (Exception e){e.printStackTrace();}}private static void readHander(SelectionKey key) {//取出当前key所关联的客户端SocketChannel client = (SocketChannel) key.channel();//取出该客户端 对应的  buffer//这个buffer是我们建立连接时传进去和 channel一对一绑定的ByteBuffer buffer = (ByteBuffer) key.attachment();buffer.clear();int read=0;try {for(;;){//从channel中读取数据写入到buffer中read = client.read(buffer);if(read==0){break;//这里可能有bug,客户端可能关掉,处理close_wait状态, 会一直监听到这个事件// 这里直接简单暴力的关掉}else if(read<0){client.close();break;}else{//对于buffer,刚刚是写,现在进行读操作,调用flipbuffer.flip();byte[] bytes = new byte[buffer.limit()];buffer.get(bytes);String str = new String(bytes);System.out.println(client.socket().getRemoteSocketAddress()+" -->" +str);}}}catch (Exception e){e.printStackTrace();}}private static void acceptHander(SelectionKey key) {try {ServerSocketChannel channel = (ServerSocketChannel) key.channel();SocketChannel client = channel.accept();client.configureBlocking(false);ByteBuffer buffer = ByteBuffer.allocate(8192);//将这个新连接交给多路复用器去管理,后面多路复用器中才能监控这个连接, 在我们去获取的时候,给我们返回有状态的连接//同时这里将channel和buffer 一对一 进行绑定,可以很方便的往里写入, 或者 读出来client.register(selector, SelectionKey.OP_READ,buffer);System.out.println("add client port:"+client.socket().getPort());count--;} catch (IOException e) {e.printStackTrace();}}}

测试使用的客户端代码还是和上篇文章中保持一致, 这里不再放了.

压测结果

以上所有说的都是理论, 而理论一定是需要实际结果来验证的, 我们这里就还是同样处理5000个连接, 并接收同样消息, 看看多路复用器的实际效果如何.
在这里插入图片描述

可以看到, 效果是非常非常明显的, 比BIO,NIO都要快太多了, 而且还代码还是单线程模型, 将其扩展成多线程, 效率将会更高.

总结

从BIO -> NIO -> 多路复用器, 我们分析了各自的缺点及演变过程, 并是实际结果对比了各自的效率, 相信你会更加印象深刻.

针对本文的测试结果总结如下:

在这里插入图片描述

今天的分享就到这里了,有问题可以在评论区留言,均会及时回复呀.
我是bling,未来不会太差,只要我们不要太懒就行, 咱们下期见.
在这里插入图片描述

相关文章:

BIO到NIO、多路复用器, 从理论到实践, 结合实际案例对比各自效率与特点(下)

文章目录 多路复用器简介多路复用器的两个阶段Java中的多路复用器封装测试代码压测结果总结 本篇文章是BIO到NIO、多路复用器, 从理论到实践, 结合实际案例对比各自效率与特点(上)的下一篇, 如果没有看的小伙伴, 可以先看下, 不然可能会不连贯. 多路复用器简介 多路复用器是对…...

Pandas数据分析教程-pandas的数据结构

pandas数据分析-pandas的数据结构 pandas 数据结构Series1. 创建Series数组2. 性质3. 索引4. 运算DataFrame1. 创建Df数组2. 性质3.索引4. 对列进行增删改Index Objects本文介绍pandas中一些常用的属性方法的概述,给读者提供快速学习的架构和思路。表格中提供的一些参数方法没…...

ChatGPT在医疗系统的应用探索动态

注意&#xff1a;本信息仅供参考&#xff0c;发布该内容旨在传递更多信息的目的&#xff0c;并不意味着赞同其观点或证实其说法。 生成式人工智能&#xff0c;如OpenAI开发的ChatGPT&#xff0c;被认为是可以颠覆医疗行业的工具。尽管该技术刚刚起步&#xff0c;但已有许多医…...

【FreeRTOS】【应用篇】任务管理相关函数

文章目录 前言一、函数解析1. 任务挂起 vTaskSuspend()① 使用场景② 设计思路③ 代码 2. 任务恢复 vTaskResume()① 作用② 设计思路③ 代码 3. 挂起任务调度器 vTaskSuspendAll()① 作用② 代码 4. 恢复任务调度器 xTaskResumeAll()① 设计思路② 代码 5. 任务删除函数 vTask…...

第一个react应用程序并添加样式

编写第一个react应用程序 将目录下的文件、src文件夹、public文件夹清空&#xff0c;项目根目录下新建一个文件index.js 在文件中写入以下代码 import React from react import ReactDOM from react-dom ReactDOM.render(<h1>欢迎进入React的世界</h1>,document.…...

Java——Object类

什么是Object类&#xff1f; 类 java.lang.Object是类层次结构的根类&#xff0c;即所有其它类的父类。每个类都使用 Object 作为超类。&#xff08;父类和超类是一个意思&#xff0c;不同的叫法&#xff09; 也就是当初的Java语言设计时&#xff0c;就将Object作为所有类的父…...

CotEditor for mac 4.0.1 中文版(开源文本编辑器)

coteditorformac是一款简单实用的基于Cocoa的macOS纯文本编辑器&#xff0c;coteditormac版本可以用来编辑网页、结构化文本、程序源代码等文本文件&#xff0c;使用起来非常方便。 CotEditor for Mac具有正则表达式搜索和替换、语法高亮、编码等实用功能&#xff0c;而CotEdi…...

【大数据】图解 Hadoop 生态系统及其组件

图解 Hadoop 生态系统及其组件 1.HDFS2.MapReduce3.YARN4.Hive5.Pig6.Mahout7.HBase8.Zookeeper9.Sqoop10.Flume11.Oozie12.Ambari13.Spark 在了解 Hadoop 生态系统及其组件之前&#xff0c;我们首先了解一下 Hadoop 的三大组件&#xff0c;即 HDFS、MapReduce、YARN&#xff0…...

c++ qt--事件过滤(第七部分)

c qt–事件过滤&#xff08;第七部分&#xff09; 一.为什么要用事件过滤 上一篇博客中我们用到了事件来进行一些更加细致的操作&#xff0c;如监控鼠标的按下与抬起&#xff0c;但是我们发现如果有很多的组件那每个组件都要创建一个类&#xff0c;这样就显得很麻烦&#xff…...

Inventor软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 Inventor软件是一款由Autodesk公司开发的三维计算机辅助设计&#xff08;CAD&#xff09;软件&#xff0c;主要用于机械设计和工程领域。它基于参数化建模技术&#xff0c;可以创建出复杂的三维模型&#xff0c;并且提供了丰富的…...

STM32F103 4G Cat.1模块EC200S使用

一、简介 EC200S-CN 是移远通信最近推出的 LTE Cat 1 无线通信模块&#xff0c;支持最大下行速率 10Mbps 和最大上行速率 5Mbps&#xff0c;具有超高的性价比&#xff1b;同时在封装上兼容移远通信多网络制式 LTE Standard EC2x&#xff08;EC25、EC21、EC20 R2.0、EC20 R2.1&a…...

38、springboot为 spring mvc 提供的静态资源管理,覆盖和添加静态资源目录

springboot为 spring mvc 提供的静态资源管理 ★ Spring Boot为Spring MVC提供了默认的静态资源管理&#xff1a; ▲ 默认的四个静态资源目录&#xff1a; /META-INF/resources > /resources > /static > /public ▲ ResourceProperties.java类的源代码&#xff0…...

Go 输出函数

Go语言拥有三个用于输出文本的函数&#xff1a; Print()Println()Printf() Print() 函数以其默认格式打印其参数。 示例 打印 i 和 j 的值&#xff1a; package mainimport "fmt"func main() {var i, j string "Hello", "World"fmt.Print(…...

L1-037 A除以B(Python实现) 测试点全过

题目 真的是简单题哈 —— 给定两个绝对值不超过100的整数A和B&#xff0c;要求你按照“ A / B 商 A/B商 A/B商”的格式输出结果。 输入格式 输入在第一行给出两个整数 A A A和 B &#xff08; − 100 ≤ A , B ≤ 100 &#xff09; B&#xff08;−100≤A,B≤100&#xff0…...

睿思BI旗舰版V5.3正式发布

发布时间&#xff1a;2023-7-20 主要更新内容: 1.增加3D地图功能 2.增加水球图 3.增加扇形图&#xff0c;在数据大屏 - 自定义组件中定义。 4.增加指标引导线功能&#xff0c;在数据大屏 - 自定义组件中定义。 5.详情页增加回调函数功能。 6.大屏/仪表盘模版下载&#xff0c;…...

基于Jenkins自动化部署PHP环境---基于rsync部署

基于基于Jenkins自动打包并部署Tomcat环境_学习新鲜事物的博客-CSDN博客环境 准备git仓库 [rootgit ~]# su - git 上一次登录&#xff1a;五 8月 25 15:09:12 CST 2023从 192.168.50.53pts/2 上 [gitgit ~]$ mkdir php.git [gitgit ~]$ cd php.git/ [gitgit php.git]$ git --b…...

学信息系统项目管理师第4版系列02_法律法规

1. 信息安全的法律体系可分为四个层面 1.1. 一般性法律法规&#xff0c;如宪法、国家安全法&#xff0c;国家秘密法 1.2. 规范和惩罚信息网络犯罪的法律&#xff0c;如刑法、《全国人大常委会关于维护互联网安全的决定》等 1.3. 直接针对信息安全的特别规定&#xff0c;如《…...

【大数据】Doris:基于 MPP 架构的高性能实时分析型数据库

Doris&#xff1a;基于 MPP 架构的高性能实时分析型数据库 1.Doris 介绍 Apache Doris 是一个基于 MPP&#xff08;Massively Parallel Processing&#xff0c;大规模并行处理&#xff09;架构的高性能、实时的分析型数据库&#xff0c;以极速易用的特点被人们所熟知&#xff…...

【rust/egui】(五)看看template的app.rs:SidePanel、CentralPanel以及heading

说在前面 rust新手&#xff0c;egui没啥找到啥教程&#xff0c;这里自己记录下学习过程环境&#xff1a;windows11 22H2rust版本&#xff1a;rustc 1.71.1egui版本&#xff1a;0.22.0eframe版本&#xff1a;0.22.0上一篇&#xff1a;这里 SidePanel 侧边栏&#xff0c;如下图 …...

MTK6833_MT6833核心板_天玑700安卓5G核心板规格性能介绍

MTK6833安卓核心板采用台积电 7nm 制程的5G SoC&#xff0c;2*Cortex-A766*Cortex-A55架构&#xff0c;搭载Android12.0操作系统&#xff0c;主频最高达2.2GHz 。内置 5G 双载波聚合技术&#xff08;2CC&#xff09;及双 5G SIM 卡功能&#xff0c;实现优异的功耗表现及实时连网…...

文献自由:ScienceDecrypting破解加密PDF的技术突破与价值重构

文献自由&#xff1a;ScienceDecrypting破解加密PDF的技术突破与价值重构 【免费下载链接】ScienceDecrypting 破解CAJViewer带有效期的文档&#xff0c;支持破解科学文库、标准全文数据库下载的文档。无损破解&#xff0c;保留文字和目录&#xff0c;解除有效期限制。 项目地…...

Scientific Reports论文返修后,从接受到正式上线的完整时间线与关键节点(附校样避坑指南)

Scientific Reports论文从接受到正式上线的全流程解析与实战指南 当你收到那封梦寐以求的"Accept"邮件时&#xff0c;兴奋之余是否也对后续流程感到迷茫&#xff1f;从论文接受到正式上线&#xff0c;Springer Nature的生产流程看似标准却暗藏诸多细节。本文将为你拆…...

5分钟Mac本地跑通32B Qwen!免费GPT-4o替代,还能5分钟造个会开浏览器+执行Shell的AI Agent

1. 硬件与模型选择 配置&#xff1a;Apple M2 Pro&#xff08;19 核 GPU&#xff09;、32GB 统一内存。 推荐模型&#xff1a;mlx-community/Qwen2.5-Coder-32B-Instruct-4bit 4bit 量化后只占 18-22GB 内存专为代码和 Agent 优化&#xff0c;Tool Calling 能力强MLX 原生支持…...

百川2-13B+OpenClaw:学术论文参考文献自动校对系统

百川2-13BOpenClaw&#xff1a;学术论文参考文献自动校对系统 1. 为什么需要参考文献自动化校对 去年写博士论文时&#xff0c;我曾在参考文献格式上栽过跟头。距离截稿还有48小时&#xff0c;导师突然指出我的参考文献列表存在三处格式不一致——有的作者名全大写&#xff0…...

readme-ai模板系统详解:如何创建自定义文档样式

readme-ai模板系统详解&#xff1a;如何创建自定义文档样式 【免费下载链接】readme-ai README file generator, powered by AI. 项目地址: https://gitcode.com/gh_mirrors/re/readme-ai 在当今开源项目中&#xff0c;专业的README文档是吸引用户和贡献者的关键。readm…...

扫雷-HTML

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>扫雷游戏</title><style>* {margin:…...

大麦网抢票自动化:从技术原理到实战落地的全方位指南

大麦网抢票自动化&#xff1a;从技术原理到实战落地的全方位指南 【免费下载链接】DamaiHelper 大麦网演唱会演出抢票脚本。 项目地址: https://gitcode.com/gh_mirrors/dama/DamaiHelper 问题引入&#xff1a;抢票困境与技术破局 在热门演出票务竞争日益激烈的当下&am…...

DataSphere Studio:企业级数据开发平台的7大核心优势与完整使用指南

DataSphere Studio&#xff1a;企业级数据开发平台的7大核心优势与完整使用指南 【免费下载链接】DataSphereStudio WeBankFinTech/DataSphereStudio: 是腾讯金融科技的一个数据开发平台&#xff0c;具有强大的数据处理&#xff0c;分析&#xff0c;可视化和机器学习功能&#…...

2026年,哪款AI最适合写小说?创作者的终极工具指南

在2026年的今天&#xff0c;AI写作工具已经深度融入小说创作的全流程。对于网文作者、短剧编剧和漫剧创作者而言&#xff0c;选择一款合适的AI工具&#xff0c;不仅能提升创作效率&#xff0c;更能直接影响作品的商业化潜力。然而&#xff0c;面对市面上琳琅满目的AI工具&#…...

3大维度掌握Ryujinx:Switch模拟器从配置到优化的全流程指南

3大维度掌握Ryujinx&#xff1a;Switch模拟器从配置到优化的全流程指南 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx Ryujinx作为一款用C#编写的开源Switch模拟器&#xff0c;为玩家…...