线程池介绍
服务器完成一项任务的时间可分为:T1:创建线程或进程时间;T2:执行任务时间;T3:销毁进程或线程时间。通常T1+T3的时间大于T2,线程池正是关注如何缩短T1和T3的时间。
线程池通过在系统中预先创建一定数量的线程,当任务请求到来时从线程池中分一个预先创建的线程去处理任务,线程在处理完任务后还可以重用,不会销毁,继续等待下次任务的到开。这样能避免大量的线程创建和销毁操作,从而节省系统资源;同时有很多任务时,也会减少创建线程的数量。
用C++11的线程相关特性,比如线程、条件变量、互斥量,让我们编写并发程序更简单。
半同步半异步线程池实现的关键技术分析
线程池又三层组成:
1. 同步服务层:不断的将新任务添加到同步队列中,可以用多路复用或者多线程来完成。一开始没看懂任务是什么,其实一个函数就是一个任务,C++11通过std::function将函数封装为类模板对象,可以将这些任务(函数)放到容器中保存起来,以进行添加读取任务操作。
2. 排队层:就是一个同步队列,处于核心地位。所有待处理的任务都存在这里,要保证队列中共享数据线程安全(加锁),还要控制任务的数量,上层服务层往队列添加任务,下层从这里取任务去执行。
3. 异步服务层: 预先创建好线程,来并行处理队列中的任务。
自己画了一张图:
代码实现与分析
用到了很多C++11的特性,里面写了很多注释,是根据自己理解分析的。
同步队列:
#include <iostream>
#include <string>
#include <stack>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <list>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
template<typename T>
class Syncqueue
{
public:
//初始化,队列的最大元素个数,开始不终止
Syncqueue( int maxsize ) : m_maxsize(maxsize),m_needStop(false){}
//往队列中添加任务,重载两个版本,左值和右值引用
void Put( const T& x )
{
Add(x);
}
void Put(T&& x)
{
Add(forward<T>(x));
}
//Take和Add类似
void Take(list<T>& list)
{
unique_lock<mutex> locker(m_mtx);
m_notEmpty.wait(locker, [this] { return m_needStop|| NotEmpty(); });//停止或者不空就继续执行,不用wait
if(m_needStop) return ;
//一次加锁,一下取出队列中的所有数据
list = move(m_queue); //通过移动,将 m_queue 转移到 list,而不是拷贝

本文介绍了一个基于C++11标准库实现的线程池,包括其设计原理、关键技术和具体实现细节。该线程池由同步服务层、排队层和异步服务层构成,有效地减少了线程创建和销毁带来的开销。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



