c++线程池的实现

线程池编程简介:

    在 我们的服务端的程序中运用了大量关于池的概念,线程池、连接池、内存池、对象池等等。使用池的概念后可以高效利用服务器端的资源,比如没有大量的线程在系 统中进行上下文的切换,一个数据库连接池,也只需要维护一定里的连接,而不是占用很多数据库连接资源。同时它们也避免了一些耗时的操作,比如创建一个线 程,申请一个数据库连接,而且可能就只使用那么一次,然后就立刻释放刚申请的资源,效率很低。

    在我的上一篇blog中已经实现一个线程基类了,在这里我们只需要实现一个线程池类ThreadPool和该线程池调度的工作线程类WorkThread即可,而且WorkThread是继承自Thread类的。

 

实现思路:

    一个简单的线程池的实现思路一般如下:

  1. ThreadPool中创建多个线程(WorkThreadk对象),每个线程均处于阻塞状态,等待任务的到来
  1. ThreadPool提供一个提交任务的接口,如post_job(ProcCallback func, void* data); post_job后会立即返回,不会阻塞
  2. ThreadPool维护一个空闲线程队列,当客户程序调用post_job()后,如果空闲队列中有空闲线程,则取出一个线程句柄,并设置任务再给出新任务通知事件即可,处理等待的线程捕捉到事件信号后便开始执行任务,执行完后将该线程句柄重新push到空闲线程队列中
  3. 该线程池采用回调函数方式

首先我们实现一个WorkThread类:

 

#include <pthread.h>
#include <vector>
#include <iostream>
using namespace std;

typedef void(*ProcCallBack)(void *);



class WorkThread;



class ThreadPool
{
    friend class WorkThread;
public:
    ThreadPool(){}
    ~ThreadPool();
    int    start_thread_pool(size_t thread_num = 5);        //启动thread_num个线程
    int    stop_thread_pool();                                      //线束线程池
    void    destroy();                                                //销毁线程池所申请的资源
    void    post_job(ProcCallBack func, void* data);        //提交任务接口,传入回调函数地址和参数

protected:
    WorkThread*    get_idle_thread();                              //从获得空闲队列中取得一个线程句柄
    void        append_idle_thread(WorkThread* pthread);    //加入到thread_vec_和idl_que_中
    void        move_to_idle_que(WorkThread* idlethread);    //将线程句柄加入到idle_que_中

private:
    size_t                thr_num_;                      //线程数目
    vector<WorkThread*>        thr_vec_;        //线程句柄集合
    vector<WorkThread*>    idle_que_;     //空闲线程队列

private:
    // not implement
    ThreadPool(const ThreadPool&);
    ThreadPool&    operator=(const ThreadPool&);
};

class WorkThread
{
    friend class ThreadPool;
public:
    WorkThread(ThreadPool* pthr_pool)
    {
        hr_pool_ = pthr_pool;
        cb_func_ = NULL;
        param_ = NULL;
    }
    ~WorkThread(){}
    void set_job(ProcCallBack func, void *param)
    {
        cb_func_ = func;
        param_ = param;
        //notify();
    }
    void run()
    {
        if (cb_func_)
        {
            cb_func_(param_);
        }
        cb_func_ = NULL;
        param_ = NULL;
        hr_pool_->move_to_idle_que(this);
    }
private:
    ThreadPool * hr_pool_;
    ProcCallBack cb_func_;
    void*        param_;
};

 

线程池实现的关键是如何创建多个线程,并且当任务来临时可以从线程池中取一个线程(也就是去得到其中一个线程的指针),然后提交任务并执行。还有一点就是 当任务执行完后,应该将该线程句柄重新加入到空闲线程队列,所以我们将ThreadPool的指针传入给了WorkThread,thr_pool_最后 可以调用move_to_idle_que(this)来将该线程句柄移到空闲队列中。

ThreadPool中一些关键代码的实现:
#include"threadpool.h"
#include<cstdio>

class ThreadPool;
int ThreadPool::start_thread_pool(size_t thread_num)
{
    thr_num_ = thread_num;
    int    ret = 0;
    for (size_t i = 0; i < thr_num_; ++i)
    {
        WorkThread*    pthr = new WorkThread(this);
        //pthr->set_thread_id(i);
        if ((ret = pthr->hr_pool_->start_thread_pool()) != 0)
        {
            printf("start_thread_pool: failed when create a work thread: %d\n", i);
            delete pthr;
            return i;
        }
        append_idle_thread(pthr);
    }
    return thr_num_;
}
int ThreadPool::stop_thread_pool()
{
    for (size_t i = 0; i < thr_vec_.size(); ++i)
    {
        WorkThread* pthr = thr_vec_[i];
        //pthr->join();
        delete pthr;
    }
    thr_vec_.clear();
    idle_que_.clear();
    return 0;
}
void ThreadPool::destroy()
{
    stop_thread_pool();
}
void ThreadPool::append_idle_thread(WorkThread* pthread)
{
    thr_vec_.push_back(pthread);
    idle_que_.push_back(pthread);
}
void ThreadPool::move_to_idle_que(WorkThread* idlethread)
{
    idle_que_.push_back(idlethread);
}
WorkThread* ThreadPool::get_idle_thread()
{
    WorkThread*    pthr = NULL;
    if (!idle_que_.empty())
    {
        vector<WorkThread*>::iterator it = idle_que_.end();
        pthr = *it;
        idle_que_.pop_back();
    }

    return pthr;
}
void ThreadPool::post_job(ProcCallBack func, void* data)
{
    WorkThread* pthr = get_idle_thread();
    while (pthr == NULL)
    {
        //Sleep(500000);
        pthr = get_idle_thread();
    }
    pthr->set_job(func, data);
}

void count(void* param)
{
    // do some your work, like: 
    int* pi = static_cast<int*>(param);
    int val = *pi + 1;
    printf("val=%d\n", val);
    delete pi;
}
int main()
{
    //程序中使用如下:
    ThreadPool* ptp = new ThreadPool();
    ptp->start_thread_pool(3);        //启动3 个线程
    ptp->post_job(count, new int(1));        //提交任务
    ptp->post_job(count, new int(2));
    ptp->post_job(count, new int(3));
    //程序线束时
    ptp->stop_thread_pool();
    return 0;
}

 

 

posted @ 2016-07-30 17:38  mahaitao617  阅读(296)  评论(0编辑  收藏  举报