1. 单线程异步
在单线程的异步模型中,异步操作通常通过事件循环机制来处理。当一个异步操作被启动后,程序会继续执行其他任务,但异步操作的结果或者状态变化会被放入事件队列中,等待事件循环处理。当事件循环处理到该事件时,会调用相应的回调函数来处理操作的结果或者状态变化。在这种情况下,不需要重新开启一个线程来执行其他任务。
-
非阻塞I/O操作: 单线程与事件循环模型中的I/O操作通常采用非阻塞的方式进行,即在发起I/O操作后,程序不会等待操作完成,而是立即返回继续执行后续的任务。这样,单线程在处理一个I/O操作时不会被阻塞,可以立即切换到处理其他任务,从而提高了程序的并发能力和响应速度。
-
事件驱动的设计: 单线程与事件循环模型采用事件驱动的设计思想,通过事件循环轮询监听各种事件的发生,例如网络数据的到达、定时器的触发、用户输入等。当某个事件发生时,事件循环会调用相应的事件处理函数来处理事件。这种设计使得程序能够同时处理多个I/O操作,而不需要为每个操作创建一个线程,节省了线程切换的开销。
-
异步回调函数: 单线程与事件循环模型通常使用异步回调函数来处理I/O操作的结果。在发起一个I/O操作时,可以指定一个回调函数,当操作完成时,系统会调用该回调函数来处理操作的结果。这种方式使得程序在等待I/O操作完成时不会被阻塞,能够继续执行其他任务,提高了程序的并发能力和吞吐量。
#include <iostream>
#include <queue>
#include <functional>
// 定义事件类型
enum EventType {
EVENT_TYPE_MESSAGE,
EVENT_TYPE_TIMER
};
// 事件结构体
struct Event {
EventType type;
std::function<void()> handler;
};
// 事件循环类
class EventLoop {
private:
std::queue<Event> eventQueue; // 事件队列
public:
// 注册事件处理器
void addEvent(EventType type, std::function<void()> handler) {
eventQueue.push({type, handler});
}
// 事件循环
void run() {
while (!eventQueue.empty()) {
Event event = eventQueue.front();
eventQueue.pop();
// 调用事件处理函数
event.handler();
}
}
};
int main() {
// 创建事件循环对象
EventLoop eventLoop;
// 注册消息事件处理器
eventLoop.addEvent(EVENT_TYPE_MESSAGE, []() {
std::cout << "Processing message..." << std::endl;
});
// 注册定时器事件处理器
eventLoop.addEvent(EVENT_TYPE_TIMER, []() {
std::cout << "Processing timer..." << std::endl;
});
// 启动事件循环
eventLoop.run();
return 0;
}
2. 多线程异步
多线程异步编程模型通常使用多个线程来处理异步任务,每个线程可以独立地执行任务,并且任务之间可以并行执行,从而提高了程序的并发能力和性能。
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
// 异步任务函数,模拟计算密集型任务
int calculate(int a, int b) {
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作
return a + b;
}
int main() {
// 创建一个异步任务,计算两个数的和
std::future<int> futureResult = std::async(std::launch::async, calculate, 10, 20);
// 主线程可以继续执行其他任务
std::cout << "Main thread continues executing other tasks..." << std::endl;
// 等待异步任务完成并获取结果
int result = futureResult.get();
// 打印计算结果
std::cout << "Result of calculation: " << result << std::endl;
return 0;
}
3. 协程
协程这个技术已经过时了,使用线程可以发挥多核的优势。在有大量IO操作业务的情况下,我们采用协程替换线程,可以到达很好的效果,一是降低了系统内存,二是减少了系统切换开销,因此系统的性能也会提升。
协程运行在线程之上,当一个协程执行完成后,可以选择主动让出,让另一个协程运行在当前线程之上。协程并没有增加线程数量,只是在线程的基础之上通过分时复用的方式运行多个协程,而且协程的切换在用户态完成,切换的代价比线程从用户态到内核态的代价小很多。