尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

并发编程(c++)——5.事件驱动

并发编程(c++)——5.事件驱动
📅 发布时间:2026/6/18 13:26:21

在并发编程中除了池和流的方式外,还存在一种基本形式,就是事件驱动。
事件驱动的思想是使用一个线程,不断循环处理任务,将任务分发给其他复用的线程,这样就通过单线程处理大量任务。

发展历程

io密集任务可以使用多线程,一个io使用一个线程。
但是如果任务过多,比如达到百万级,此时线程数量也会达到百万级别,此时系统支持不了,会崩溃。
或者说使用线程池,但是线程数量也需要很大,频繁的切换线程也会带来大量的开销。

这里有一个前提是,io任务的处理机制基本一致,可以用一个函数处理大量任务。
此时可以考虑一种方式,使用少量线程,完成大量io任务。
使用一个死循环,一个队列,队列中存储io任务,死循环中不断处理io,这样就可以通过单线程处理百万io。

但是这样会有阻塞问题,处理io会使cpu等待,所以需要将请求io和处理io分离。
这样cpu只处理请求io,处理io交给其他线程处理,能充分利用cpu资源。

同时还有一个问题,循环内部会查询io任务队里,但如果io队列里没有任务,这个循环就没有意义,此时cpu会空转,浪费资源。
所以需要一种机制,当io队列为空时,让cpu等待,当有任务时再唤醒cpu,继续处理任务。

背景问题

1.使用多线程处理io密集任务,当线程数量过大,带来系统支持线程数不足,线程切换资源消耗大。
2.cpu和io处理时间差大,带来的阻塞问题。
3.非阻塞循环,带来cpu空转。

解决方案

1.循环
使用一个死循环,不断读取任务和将任务分配给处理器。
解决多线程处理,使用单线程实现。
2.分离
发起io请求后,不等待io返回,继续处理其他任务,当io返回后,再处理io返回结果。
解决阻塞问题。
3.监督
循环内部监视任务,当任务为空时,让cpu等待,当有任务时再唤醒cpu,继续处理任务。
解决cpu空转问题。

实现

将所有任务抽象为不同的数据和对应的处理方式,这就带获得了各个组成部分。

实现因素

1.事件
将类型和数据抽象为一个结构体,这个结构体就是事件。
2.任务队列
将要处理的事件放入队列中,循环从队列中获取事件,处理事件。
3.处理器队列
将任务类型和处理方式抽象为一个map,key为任务类型,value为处理方式,放置在一个队列中,处理任务时搜索这个队列,找到对应任务类型,执行处理方式。
4.注册
将处理器注册到处理器队列中。
5.循环
死循环,调度任务队列和处理器队列,监督任务队列,当任务队列为空时,让cpu等待,当有任务时再唤醒cpu,继续处理任务。
6.分发
有任务时查找任务对应的处理器,将数据输入处理器中,处理数据。

#include<string>#include<queue>#include<map>#include<vector>#include<functional>#include<mutex>structevent{inttype;std::string data;};// 事件驱动类,用于处理事件驱动的程序classEventDrive{private:// 事件队列,用于存储待处理的事件std::queue<event>queue_events;// 事件处理器映射表,键为事件类型,值为对应的事件处理函数列表std::map<int,std::vector<std::function<void(constevent&)>>>map_event_handlers;// 互斥锁,用于保证线程安全std::mutex mut;// 运行状态标志,true表示正在运行,false表示已停止boolis_running;public:// 注册处理器:为特定类型的事件注册一个处理函数voidon(inttype,std::function<void(constevent&)>handler);// 循环处理事件:持续从队列中取出事件并处理,直到is_running为falsevoidrun();// 添加事件:将新事件添加到事件队列中voidadd_event(inttype,std::string data);// 处理事件:根据事件类型查找并执行对应的处理函数voidhandle_event(constevent&e);// 停止事件驱动voidstop();};// 注册事件voidEventDrive::on(inttype,std::function<void(constevent&)>handler){map_event_handlers[type].push_back(handler);}// 循环处理事件voidEventDrive::run(){is_running=true;while(is_running){if(queue_events.empty()){continue;}else{std::lock_guard<std::mutex>lock(mut);event e=queue_events.front();queue_events.pop();handle_event(e);}std::this_thread::sleep_for(std::chrono::milliseconds(1));}}// 添加事件voidEventDrive::add_event(inttype,std::string data){std::lock_guard<std::mutex>lock(mut);event e;e.type=type;e.data=data;queue_events.push(e);}// 处理事件voidEventDrive::handle_event(constevent&e){autoit=map_event_handlers.find(e.type);if(it!=map_event_handlers.end()){for(auto&handler:it->second){handler(e);}}}// 停止事件驱动voidEventDrive::stop(){is_running=false;}

使用

1.注册
将处理器以函数的方式注册到处理器队列中。
2.分析线程循环
将事件驱动的循环在主线程外部执行,这样主线程用于输入任务。
3.载入任务
将任务以事件的方式载入任务队列中。

#include"event_drive.hpp"#include<iostream>intmain(){EventDrive envent_drive;//注册事件envent_drive.on(1,[](constevent&e){std::cout<<"handler 1,收到事件1:"<<e.data<<std::endl;});envent_drive.on(2,[](constevent&e){std::cout<<"handler 2,收到事件2:"<<e.data<<std::endl;});envent_drive.on(1,[](constevent&e){std::cout<<"handler 3,也收到事件1:"<<e.data<<std::endl;});// 启动事件循环std::threadloop_thread([&envent_drive](){envent_drive.run();});// 发送事件envent_drive.add_event(1,"data 1");envent_drive.add_event(2,"data 2");envent_drive.add_event(1,"data 3");// 停止事件循环std::this_thread::sleep_for(std::chrono::milliseconds(100));envent_drive.stop();loop_thread.join();return0;}

结果

handler 1,收到事件1:data 1 handler 3,也收到事件1:data 1 handler 2,收到事件2:data 2 handler 1,收到事件1:data 3 handler 3,也收到事件1:data 3

总结

使用事件驱动的方式,将任务抽象为事件,将处理方式抽象为处理器,将任务和处理器注册到事件驱动中,事件驱动循环处理任务。

相关新闻

  • 基于NXP GenAVB栈的AVB/AVDECC音频流配置实战指南
  • TWR-56F8257开发板硬件解析与实战:DSC电机控制平台设计精髓
  • 解决 NVIDIA Profile Inspector 配置文件导入失败的 NVAPI_ACCESS_DENIED 错误

最新新闻

  • 石家庄众成学校联系电话 校区地址 官方联系方式 - 资讯纵览
  • 2026 佛山靠谱的卫生间防水补漏公司推荐 top5 推荐 - 防水资讯
  • Res-Downloader终极指南:一键下载全网视频音频资源的完整解决方案
  • 2026年6月郑州搬家别瞎找!本地实测2家靠谱一站式搬家公司,附近优选、急速上门 - 资讯纵览
  • 旧Mac重获新生:OpenCore Legacy Patcher让你的老设备畅享最新macOS
  • 2026 南昌靠谱的卫生间防水补漏公司推荐 top5 推荐 - 防水资讯

日新闻

  • 2026年不锈钢卷板厂家推荐排行榜:冷轧热轧/304/201不锈钢卷板,高颜值耐腐蚀源头厂家实力精选 - 企业推荐官【官方】
  • FLUX.1-dev FP8模型实战指南:24GB以下显卡高效部署方案
  • 2026佛山长途搬家价目表:跨省跨市搬家费用完整计算指南 - 从来都是英雄出少年

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号