多线程的N种模式
多线程有两种基本模式
- 线程池模式
- 生产者/消费者模式
总结
- 方案1 适合有少量多线程处理
- 方案2 适合常驻的对延时要求不高的多线程
- 方案3 适合有大量任务不停的产生,并且对延时敏感的多线程
情景模拟
- 我们有1W个任务要处理
- 我们的运行环境 最多支持并行100个任务
线程池模式
- 我们新建一个 线程池,设置他只允许 并行100个任务
- 我们读取任务列表 依次创建1W个线程,并且放入线程池运行
生产者/消费者模式
- 我们 先设计一个任务队列,可以存取任务
- 任务的 增加/取出 等操作 一定要
互斥
- 我们创建100个线程
- 每个线程都反复取出 任务队列里的任务,并且处理
- 直至所有任务都处理后退出
多线程设计模型
方案1 即时创建
- 线程运行后,自己结束
- 没有任务时不创建线程
- 有任务时创建
线程池
优点:
- 任务较少时节省资源
缺点:
- 任务较多时,线程池中会有大量线程被创建后等待
- 大量闲置线程会占据很多内存
方案2 线程永生
- 线程的数量是恒定的
- 没有任务时 线程自己
定时检查
是否有任务 - 有任务时 取出并处理任务
优点:
- 即使任务数量很大也不会有大量线程被创建后等待
缺点:
- 即使任务很少 也会占用一部分资源
- 检查任务/等待任务 本就会造成一些延时
方案3 即时唤醒_永生线程(推荐)
- 子线程的数量是恒定的
- 子线程 没有任务时
等待唤醒
WaitForSingleObject
我们在主线程中判断有多少任务,并且决定 唤醒几个线程
ReleaseSemaphore
- 所有子线程会循环处理所有任务
- 子线程发现没有任务时不要
ReleaseSemaphore
,直接进入休眠状态WaitForSingleObject
- 重复步骤三
优点:
- 解决了
线程永生
导致的 任务处理延时 - 解决了
即时创建
导致的 大量子线程闲置/等待 - 可以动态决定 任务并行数量
缺点:
- 代码移植性较差
- 非常依赖 底层的唤醒机制
- 在某些情况下 不如
线程永生
伪代码
//定义子线程
DWORD my_thread()
{
while(等待被唤醒)
{
while(1)
{
//=============线程互斥代码块
if(有任务){
取任务;
任务列表删除 我们选择的任务;
}else{
n_count 原子+1;
break; //我们回到最外层 while
}
//=============线程互斥代码块
//处理我们拿到的任务
}
}
}
//定义 主线程
1 分析任务状态
2 根据需要 唤醒线程
3 等待 线程全部结束
4 结束运行/回到第一步