C++线程池实战

一 线程池的定义

这里的池是是形象的说法。线程池就是有一堆已经创建好的线程,初始都是处于空闲等待状态。当有新任务需要处理的时候,就从这堆线程(这堆线程比喻为线程池)中取出一个空闲等待的线程来处理该任务,当任务处理完毕后,就再把该线程放回池中(一般就是将线程状态设置为空闲),以供后面的任务继续使用。当池中的线程全部处于忙碌状态,线程池中没有可用的空闲等待线程,此时根据需要选择创建一个新的线程并置入池中,或者通知任务当前线程池里所有线程都在忙,等待片刻再尝试。

二 使用线程池的原因

线程的创建或销毁相对于进程的创建和销毁来说是轻量级的(开销没进程那么大),但是当我们的任务需要进行大量线程的创建和销毁操作时,这些开销合在一起就比较大了。线程池的好处在于线程复用,某个线程在处理完一个任务后,可以继续处理下一个任务,而不用销毁后再创建,这样可以避免无谓的开销,因此尤其适合连续产生大量并发任务的场合。

三 实战

1 thread_pool.h

#ifndef __THREAD_POOL_H
#define __THREAD_POOL_H

#include <vector>
#include <string>
#include <pthread.h>

using namespace std;

/*执行任务的类:设置任务数据并执行*/
class CTask {
protected:
    string m_strTaskName;   //任务的名称
    void* m_ptrData;    //要执行的任务的具体数据

public:
    CTask() = default;
    CTask(string &taskName)
        : m_strTaskName(taskName)
        , m_ptrData(NULL) {}
    virtual int Run() = 0;
    void setData(void* data);   //设置任务数据
  
    virtual ~CTask() {}
    
};

/*线程池管理类*/
class CThreadPool {
private:
    static vector<CTask*> m_vecTaskList;    //任务列表
    static bool shutdown;   //线程退出标志
    int m_iThreadNum;   //线程池中启动的线程数
    pthread_t *pthread_id;  //线程列表
  
    static pthread_mutex_t m_pthreadMutex;  //线程同步锁
    static pthread_cond_t m_pthreadCond;    //线程同步条件变量
  
protected:
    static void* ThreadFunc(void *threadData);  //新线程的线程回调函数
    static int MoveToIdle(pthread_t tid);   //线程执行结束后,把自己放入空闲线程中
    static int MoveToBusy(pthread_t tid);   //移入到忙碌线程中去
    int Create();   //创建线程池中的线程
  
public:
    CThreadPool(int threadNum);
    int AddTask(CTask *task);   //把任务添加到任务队列中
    int StopAll();  //使线程池中的所有线程退出
    int getTaskSize();  //获取当前任务队列中的任务数
};

#endif

2  thread_pool.cpp

#include "thread_pool.h"
#include <cstdio>

void CTask::setData(void* data) {
    m_ptrData = data;
}

//静态成员初始化
vector<CTask*> CThreadPool::m_vecTaskList;
bool CThreadPool::shutdown = false;
pthread_mutex_t CThreadPool::m_pthreadMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t CThreadPool::m_pthreadCond = PTHREAD_COND_INITIALIZER;

//线程管理类构造函数
CThreadPool::CThreadPool(int threadNum) {
    this->m_iThreadNum = threadNum;
    printf("I will create %d threads.\n", threadNum);
    Create();
}

//线程回调函数
void* CThreadPool::ThreadFunc(void* threadData) {
    pthread_t tid = pthread_self();
    while (1)
    {
        pthread_mutex_lock(&m_pthreadMutex);
        //如果队列为空,等待新任务进入任务队列
        while (m_vecTaskList.size() == 0 && !shutdown)
            pthread_cond_wait(&m_pthreadCond, &m_pthreadMutex);
        
        //关闭线程
        if (shutdown)
        {
            pthread_mutex_unlock(&m_pthreadMutex);
            printf("[tid: %lu]\texit\n", pthread_self());
            pthread_exit(NULL);
        }
        
        printf("[tid: %lu]\trun: ", tid);
        vector<CTask*>::iterator iter = m_vecTaskList.begin();
        //取出一个任务并处理之
        CTask* task = *iter;
        if (iter != m_vecTaskList.end())
        {
            task = *iter;
            m_vecTaskList.erase(iter);
        }
        
        pthread_mutex_unlock(&m_pthreadMutex);
        
        task->Run();    //执行任务
        printf("[tid: %lu]\tidle\n", tid);
        
    }
    
    return (void*)0;
}

//往任务队列里添加任务并发出线程同步信号
int CThreadPool::AddTask(CTask *task) {
    pthread_mutex_lock(&m_pthreadMutex);    
    m_vecTaskList.push_back(task);  
    pthread_mutex_unlock(&m_pthreadMutex);  
    pthread_cond_signal(&m_pthreadCond);    
    
    return 0;
}

//创建线程
int CThreadPool::Create() {
    pthread_id = new pthread_t[m_iThreadNum];
    for (int i = 0; i < m_iThreadNum; i++)
        pthread_create(&pthread_id[i], NULL, ThreadFunc, NULL);
        
    return 0;
}

//停止所有线程
int CThreadPool::StopAll() {    
    //避免重复调用
    if (shutdown)
        return -1;
    printf("Now I will end all threads!\n\n");
    
    //唤醒所有等待进程,线程池也要销毁了
    shutdown = true;
    pthread_cond_broadcast(&m_pthreadCond);
    
    //清楚僵尸
    for (int i = 0; i < m_iThreadNum; i++)
        pthread_join(pthread_id[i], NULL);
    
    delete[] pthread_id;
    pthread_id = NULL;
    
    //销毁互斥量和条件变量
    pthread_mutex_destroy(&m_pthreadMutex);
    pthread_cond_destroy(&m_pthreadCond);
    
    return 0;
}

//获取当前队列中的任务数
int CThreadPool::getTaskSize() {    
    return m_vecTaskList.size();
}

3 test.cpp

#include "thread_pool.h"   
#include <cstdio>         
#include <stdlib.h>         
#include <unistd.h>

class CMyTask:public CTask{
    public:
        CMyTask()=default;
        int Run(){
            printf("%s\n",(char*)m_ptrData);
            int x =rand()%4+1;
            sleep(x);
            return 0;
        }
        ~CMyTask(){}
};

int main(int argc, const char* argv[])
{
    CMyTask taskobj;
    char szTmp[]="hello!";
    taskobj.setData((void*)szTmp);
    CThreadPool threadpool(6);   //线程池大小为6
    
    for(int i=0;i<10;i++)
        threadpool.AddTask(&taskobj);
    
    while(1){
        printf("There are still %d tasks need to handle\n",threadpool.getTaskSize());
        
        //任务队列已经没有任务了
        if(threadpool.getTaskSize()==0)
        {
            //清除线程池
            if(threadpool.StopAll()==-1)
            {
                printf("Thread pool clear,exit\n");
                exit(0);
            }
        }
        sleep(2);
        printf("2 seconds later...\n");
    }
    return 0;
}

四 运行结果

[root@localhost test]# g++ -o test test.cpp thread_pool.cpp -lpthread -std=c++11
[root@localhost test]# ./test
I will create 6 threads.
There are still 10 tasks need to handle
[tid: 139862531479296]    run: hello!
[tid: 139862523086592]    run: hello!
[tid: 139862565050112]    run: hello!
[tid: 139862556657408]    run: hello!
[tid: 139862548264704]    run: hello!
[tid: 139862539872000]    run: hello!
2 seconds later...
There are still 4 tasks need to handle
[tid: 139862565050112]    idle
[tid: 139862565050112]    run: hello!
[tid: 139862548264704]    idle
[tid: 139862548264704]    run: hello!
[tid: 139862523086592]    idle
[tid: 139862523086592]    run: hello!
[tid: 139862548264704]    idle
[tid: 139862548264704]    run: hello!
[tid: 139862539872000]    idle
2 seconds later...
There are still 0 tasks need to handle
Now I will end all threads!

[tid: 139862531479296]    idle
[tid: 139862531479296]    exit
[tid: 139862556657408]    idle
[tid: 139862556657408]    exit
[tid: 139862539872000]    exit
[tid: 139862565050112]    idle
[tid: 139862565050112]    exit
[tid: 139862523086592]    idle
[tid: 139862523086592]    exit
[tid: 139862548264704]    idle
[tid: 139862548264704]    exit
2 seconds later...
There are still 0 tasks need to handle
Thread pool clear,exit

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值