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

郑州做网站好的公司太原搜索排名提升

郑州做网站好的公司,太原搜索排名提升,做兼职有哪些网站,做外贸兼职的网站设计首先,要搞懂一点,异步操作本质上也是并发,我们想要在线程级别实现异步并发基本就靠三种方式: 多线程并发回调函数协程 今天我们讨论的是回调函数,我们如何通过回调函数来实现异步操作呢? 非阻塞I/O操作回…

首先,要搞懂一点,异步操作本质上也是并发,我们想要在线程级别实现异步并发基本就靠三种方式:

  • 多线程并发
  • 回调函数
  • 协程

今天我们讨论的是回调函数,我们如何通过回调函数来实现异步操作呢?

  1. 非阻塞I/O操作+回调函数实现异步IO
  2. 基于定时器+回调函数实现异步任务调度
  3. 事件队列+回调函数

我们就分别来实现一下他们吧,代码比较长,请耐心阅读。

非阻塞I/O+回调

这种方式允许程序在等待 I/O 操作完成时继续执行其他任务,从而提高并发性和性能。

我们可以使用标准 C++ 库和 C++11 中的线程库来实现一个基于 epoll 的非阻塞 I/O 和回调函数的示例。epoll 是 Linux 提供的高效 I/O 多路复用机制,适用于处理大量并发连接。我们将使用 epoll 来实现异步 I/O,并使用回调函数处理完成的 I/O 操作。

实例代码:使用 epoll 实现非阻塞 I/O 和回调函数

#include <sys/epoll.h>
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
#include <cstring>
#include <functional>
#include <unordered_map>
#include <vector>
#include <thread>
#include <chrono>void set_non_blocking(int fd) {int flags = fcntl(fd, F_GETFL, 0);if (flage == -1) {throw std::runtime_error("fcntl get error");}if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {throw std::runtime_error("fcntl set error");}
}//事件处理器类
class EventLoop {
public:EventLoop() {epollFd_ = epoll_create1(0);if (epoll_fd == -1) {throw std::runtime_error("epoll_creat1 error");}}~EpollLoop() {close(epoll_fd);}//添加文件描述符及其对应的回调函数void add_fd(int fd, std::function<void(int)> cb) {set_non_blocking(fd);epoll_event event;event.events = EPOLLIN | EPOLLET;event.data.fd = fd;if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &event) == -1) {throw std::runtime_error("epoll_ctl add error");}callbacks_[fd] = cb;}//运行时间循环void run() {while (running_) {std::vector<epoll_event> events(10);int numActives = epoll_wait(epollFd_, events.data(), events.size(), -1);if (numActives == -1) {throw std::runtime_error("epoll_wait error");}for (int i = 0; i < n; ++i) {int fd = events[i].data.fd;if (callbacks_.find(fd) != callbacks_.end()) callbacks[fd](fd);}}}//停止事件循环void stop() {return = false;}private:int epollFd_; //epoll实例std::unordered_map<int, std::function<void(int)>> callbacks_;bool running_ = true;
};// 示例回调函数,处理标准输入的读取
void handle_stdin(int fd) {char buffer[128];ssize_t n = read(fd, buffer, sizeof(buffer) - 1);if (n > 0) {buffer[n] = '\0';std::cout << "Read from stdin: " << buffer << std::endl;} else if (n == 0) {std::cout << "EOF from stdin" << std::endl;} else {if (errno != EAGAIN && errno != EWOULDBLOCK) {std::ceer << "Read error: " <<  strerror(errno) << std::endl;}	}
}int main () {try {EventLoop loop;//注册标准输入的文件描述符和回调函数loop.add_fd(STDIN_FILENO, handle_stdin);//运行事件循环std::thread loop_thread([&loop]() {loop.run();});//模拟只线程的其他工作std::this_thread::sleep_for(std::chrono::seconds(10));//停止事件循环loop.stop();loop_thread.join();} catch (const std::exception &e) {std::cerr << "Exception: " << e.what() << std::endl;return 1}return 0;
}

在该示例中,由于是非阻塞IO,所以如果有两个 fd 对应的事件被激活,那么他们会循环执行各自的回调操作,因为我们的EventLoop里面是又一个 while 循环的,如果这两个 fd 如果都是读一个很大很大的文件,那么他们在while循环中会交替执行各自的回调任务,实现异步操作。

基于定时器+回调函数实现异步任务调度

通过定时器和回调函数,可以在单线程环境中实现异步任务调度。在这个示例中,我们实现了一个简单的 Web 服务器定时清理过期会话的功能。类似的技术可以应用于其他需要定时任务调度的场景,如定时备份、日志轮换、定时数据采集等。

1. SessionManager 类

这个类负责管理用户会话,提供添加、删除和清理过期会话的方法。

class SessionManager {
#include <iostream>
#include <unordered_map>
#include <chrono>
#include <functional>
#include <thread>
#include <vector>
#include <algorithm>class SessionManager {
public:void add_session(const std::string& session_id) {sessions[session_id] = std::chrono::steady_clock::now();}void remove_session(const std::string& session_id) {sessions.erase(session_id);}void clean_expired_sessions(std::chrono::seconds timeout) {auto now = std::chrono::steady_clock::now();for (auto it = sessions.begin(); it != sessions.end(); ) {if (now - it->second > timeout) {std::cout << "Removing expired session: " << it->first << std::endl;it = sessions.erase(it);} else {++it;}}}private:std::unordered_map<std::string, std::chrono::steady_clock::time_point> sessions;
};
  • add_session:添加一个新会话,记录会话 ID 和当前时间。
  • remove_session:删除指定的会话。
  • clean_expired_sessions:清理过期会话,检查所有会话,如果会话时间超过指定的超时时间,则删除会话。

2. EventLoop类

这个类管理定时任务,通过维护一个事件列表并运行事件循环,在指定时间间隔内执行任务。

class EventLoop {
public:void add_event(std::function<void()> callback, std::chrono::milliseconds interval) {auto next_run = std::chrono::steady_clock::now() + interval;events.emplace_back(next_run, interval, callback);}void run() {while (running) {auto now = std::chrono::steady_clock::now();for (auto& event : events) {if (now >= event.next_run) {event.callback();event.next_run = now + event.interval;}}std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 小休眠,减少CPU占用}}void stop() {running = false;}private:struct Event {std::chrono::steady_clock::time_point next_run;std::chrono::milliseconds interval;std::function<void()> callback;Event(std::chrono::steady_clock::time_point nr, std::chrono::milliseconds i, std::function<void()> cb): next_run(nr), interval(i), callback(cb) {}};std::vector<Event> events;bool running = true;
};
  • add_event:添加一个新的定时事件,指定回调函数和时间间隔。
  • run:启动事件循环,循环检查所有事件,如果事件到期则执行回调函数,并更新下一次执行时间。
  • stop:停止事件循环。

3. 回调函数

定义一个回调函数,用于清理过期会话。
如果我们定义两个不同任务的回调函数,那么是不是就可以在某段时间实现多个任务了呢?

void clean_sessions_task(SessionManager& session_manager, std::chrono::seconds timeout) {session_manager.clean_expired_sessions(timeout);
}

这个函数调用 SessionManager 的 clean_expired_sessions 方法来清理过期会话。

4. main 函数

int main() {SessionManager session_manager;EventLoop event_loop;// 添加一些示例会话session_manager.add_session("session1");std::this_thread::sleep_for(std::chrono::seconds(1));session_manager.add_session("session2");// 每2秒清理一次过期会话(假设过期时间为3秒)event_loop.add_event(std::bind(clean_sessions_task, std::ref(session_manager), std::chrono::seconds(3)), std::chrono::seconds(2));// 运行事件循环std::thread event_loop_thread([&event_loop]() {event_loop.run();});// 模拟服务器运行std::this_thread::sleep_for(std::chrono::seconds(10));// 停止事件循环event_loop.stop();event_loop_thread.join();return 0;
}
  1. 创建 SessionManager 和 EventLoop 对象。
  2. 添加两个示例会话,分别在 0 秒和 1 秒时添加。
  3. 添加一个定时事件,每 2 秒调用一次 clean_sessions_task 来清理过期会话,过期时间为 3 秒。
  4. 启动一个线程运行事件循环。
  5. 主线程模拟服务器运行 10 秒钟。
  6. 停止事件循环并等待事件循环线程结束。

如果我们添加两个定时事件,并且打开循环,那么不是就在某段时间实现了异步任务调度呢?

基于事件队列+回调函数实现异步操作

这个示例展示了如何使用标准 C++ 库和 C++11 线程库,通过事件队列和回调函数在单线程中实现异步任务调度。具体来说,我们实现了一个简单的系统,可以调度并执行延迟任务。

1.EventLoop 类

这个类管理定时任务,通过维护一个事件列表并运行事件循环,在指定时间间隔内执行任务。

class EventLoop {
public:// 添加一个新的定时事件void add_event(std::function<void()> callback, std::chrono::milliseconds interval) {auto next_run = std::chrono::steady_clock::now() + interval;events.emplace_back(next_run, interval, callback);}// 运行事件循环void run() {while (running) {auto now = std::chrono::steady_clock::now();for (auto& event : events) {if (now >= event.next_run) {event.callback(); // 执行回调函数event.next_run = now + event.interval; // 更新下一次执行时间}}std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 小休眠,减少CPU占用}}// 停止事件循环void stop() {running = false;}private:struct Event {std::chrono::steady_clock::time_point next_run;std::chrono::milliseconds interval;std::function<void()> callback;Event(std::chrono::steady_clock::time_point nr, std::chrono::milliseconds i, std::function<void()> cb): next_run(nr), interval(i), callback(cb) {}};std::vector<Event> events;bool running = true;
};
  • add_event:添加一个新的定时事件,指定回调函数和时间间隔。
    • 参数 callback 是一个回调函数,当事件触发时调用。
    • 参数 interval 是一个时间间隔,表示事件应该在多长时间后执行。
    • next_run 记录了事件的下一次执行时间。
  • run:启动事件循环,循环检查所有事件,如果事件到期则执行回调函数,并更新下一次执行时间。
    • while (running):事件循环在 running 为 true 时持续运行。
    • event.callback():执行回调函数,表示事件触发。
    • event.next_run = now + event.interval:更新事件的下一次执行时间。
    • std::this_thread::sleep_for(std::chrono::milliseconds(10)):通过短暂休眠来减少 CPU 占用。
  • stop:停止事件循环,将 running 设置为 false。

2. 回调函数

定义两个简单的回调函数,用于示例任务。

void say_hello() {std::cout << "Hello, World!" << std::endl;
}void say_goodbye() {std::cout << "Goodbye, World!" << std::endl;
}

3.main函数

设置并运行事件循环,添加一些示例任务,并定期执行这些任务。

int main() {EventLoop loop;// 添加定时事件loop.add_event(say_hello, std::chrono::seconds(1)); // 每1秒执行一次loop.add_event(say_goodbye, std::chrono::seconds(2)); // 每2秒执行一次// 运行事件循环loop.run();return 0;
}

异步任务的实现

异步任务的实现核心在于 EventLoop 类中的 add_event 和 run 方法:

  • add_event 方法将任务(回调函数)和执行时间(间隔)添加到事件队列中。
  • run 方法启动事件循环,定期检查事件队列,触发到期的任务,并通过回调函数执行这些任务。

具体来说,异步任务的执行发生在以下代码行:

if (now >= event.next_run) {event.callback(); // 执行回调函数event.next_run = now + event.interval; // 更新下一次执行时间
}
  • event.callback():当当前时间 now 大于等于 event.next_run 时,执行回调函数,表示异步任务触发并执行。

这个机制允许在单线程环境中,通过事件队列和回调函数实现异步任务调度,无需多线程或协程。每个任务在指定的时间间隔后触发,保持事件循环的运行和任务的调度。

事件队列\定时器 + 回调真的能实现异步任务吗

当回调任务是一个非常耗时的操作时,如果在单线程中执行,确实会导致事件循环被阻塞,从而影响其他任务的执行。这违背了异步执行的初衷,即不阻塞程序的其他部分。

为了解决这个问题,主要还是以下方法:

  • 使用线程池
    • 我们可以使用一个线程池来处理耗时的任务,从而避免阻塞事件循环。线程池可以并发执行多个任务,确保事件循环保持响应。

文章转载自:
http://saffron.c7623.cn
http://casal.c7623.cn
http://outlet.c7623.cn
http://dessert.c7623.cn
http://antihemophilic.c7623.cn
http://acetated.c7623.cn
http://craniofacial.c7623.cn
http://neurite.c7623.cn
http://bivalent.c7623.cn
http://cobnut.c7623.cn
http://yogism.c7623.cn
http://crowdy.c7623.cn
http://forky.c7623.cn
http://cinetheodolite.c7623.cn
http://cruciform.c7623.cn
http://tzaristic.c7623.cn
http://milliwatt.c7623.cn
http://peteman.c7623.cn
http://virgule.c7623.cn
http://supercilious.c7623.cn
http://management.c7623.cn
http://nautophone.c7623.cn
http://renata.c7623.cn
http://springbok.c7623.cn
http://tectonism.c7623.cn
http://mothball.c7623.cn
http://homotypic.c7623.cn
http://offertory.c7623.cn
http://greensick.c7623.cn
http://interfoliar.c7623.cn
http://hedonics.c7623.cn
http://tanniferous.c7623.cn
http://behindhand.c7623.cn
http://manifold.c7623.cn
http://lawson.c7623.cn
http://forcibly.c7623.cn
http://subparagraph.c7623.cn
http://canalization.c7623.cn
http://messerschmitt.c7623.cn
http://summable.c7623.cn
http://yankeedom.c7623.cn
http://imposturous.c7623.cn
http://envenomation.c7623.cn
http://omen.c7623.cn
http://doomsday.c7623.cn
http://economical.c7623.cn
http://reversional.c7623.cn
http://ramachandra.c7623.cn
http://haemoglobinometry.c7623.cn
http://litoral.c7623.cn
http://cooker.c7623.cn
http://circumlocutory.c7623.cn
http://soapsuds.c7623.cn
http://tsankiang.c7623.cn
http://tracheobronchial.c7623.cn
http://barrowman.c7623.cn
http://polarizability.c7623.cn
http://sickener.c7623.cn
http://kazakh.c7623.cn
http://textile.c7623.cn
http://gaup.c7623.cn
http://autochanger.c7623.cn
http://pierage.c7623.cn
http://catmint.c7623.cn
http://fertilization.c7623.cn
http://fratch.c7623.cn
http://beehouse.c7623.cn
http://hypersthenic.c7623.cn
http://floodwater.c7623.cn
http://decomposable.c7623.cn
http://desultoriness.c7623.cn
http://orthopteran.c7623.cn
http://unturned.c7623.cn
http://responaut.c7623.cn
http://distinctness.c7623.cn
http://carcinoma.c7623.cn
http://lowveld.c7623.cn
http://hia.c7623.cn
http://increasedly.c7623.cn
http://dynamometer.c7623.cn
http://meanings.c7623.cn
http://antialien.c7623.cn
http://manxwoman.c7623.cn
http://precative.c7623.cn
http://hootananny.c7623.cn
http://moistureless.c7623.cn
http://nostrum.c7623.cn
http://princess.c7623.cn
http://gyneocracy.c7623.cn
http://macron.c7623.cn
http://clobber.c7623.cn
http://marble.c7623.cn
http://groenendael.c7623.cn
http://ontogenic.c7623.cn
http://portage.c7623.cn
http://anna.c7623.cn
http://demythify.c7623.cn
http://atonicity.c7623.cn
http://cubature.c7623.cn
http://statism.c7623.cn
http://www.zhongyajixie.com/news/84547.html

相关文章:

  • 专业网站建设搭建sem是什么品牌
  • wordpress火车国外seo大神
  • 口碑好的购物网站建设百度精简版入口
  • 桂林手机网站制作网络推广专员是做什么的
  • 云南省建设监理协会网站成都seo经理
  • 如何做网站页面赚钱产品策划推广方案
  • 网站制作好公司新产品的推广销售方法
  • 我做的网站怎么提升排名最火网站排名
  • 建设网站 (公司)app推广员好做吗
  • 怎么做网站下载链接公司网站的推广方案
  • 做新闻h5网站微信视频号可以推广吗
  • 中国50强企业管理培训机构关键词优化包年推广
  • 福建石狮有做网站的没学网络与新媒体后悔死了
  • b站推广是什么意思海外推广渠道都有哪些
  • 网站建设彩铃高级seo优化招聘
  • 那个网站可以找人做兼职广告公司怎么找客户资源
  • 中国菲律宾冲突岛屿安卓优化大师下载安装
  • 做网站毕设答辩问题网站搭建流程
  • 网站seo推广方案一键生成个人网站
  • 天元建设集团有限公司标志宁波seo在线优化公司
  • 电子商务网站建设特色网站排名优化查询
  • 无锡网站制作电话网站排名查询工具
  • 家具网站建设规划书网络平台建设及运营方案
  • 东莞品牌网站建设18款免费软件app下载
  • 一品威客做任务要给网站钱吗推广点击器
  • seo网站推广的目的包括哪个方面软文大全800字
  • 怎么做网站推广平台互联网培训
  • 长春做网站哪家便宜百度竞价排名魏则西事件分析
  • 杭州 网站建设网站株洲seo优化公司
  • 个人域名网站可以做企业站吗免费打广告网站