一个C++线程池

来源:互联网 发布:东莞三级分销系统源码 编辑:程序博客网 时间:2024/06/11 11:22
当一个作业来的时候,能够在线程池中取出一个线程来run这个作业,这在服务器代码中尤其常见。
1,为什么要用线程池?
一些对象的创建和销毁会很耗用资源,“池化资源”能够尽可能的减少创建和减少销毁对象的次数,其采用的多线程机制也能显著的减少处理器单元的闲置时间。

2,线程池的实现
线程池主要分为四个组成部分:线程池管理器,工作线程,任务接口和任务队列
线程池管理器主要是管理创建线程池和销毁线程池中的线程,工作线程主要是正在工作的线程池中的线程,不会超过线程池中的线程总数,任务接口主要和pthread_create的第三个参数有关系,也就是线程创建函数需要执行的函数,任务队列主要是在任务到来的时候会将其放在任务队列当中,如果在短时间内到来的任务数目过多的话(多于线程池中的线程数),就只能在任务队列中的存放还不能被线程池中的线程执行的任务。
代码代码分析(linux):
.h文件:
  1. #ifndef THREAD_POOL_H_
  2. #define THREAD_POOL_H_
  3. #include <stdlib.h>
  4. #include <iostream>
  5. #include <pthread.h>
  6. #include <vector>
  7. using namespace std;
  8. class Thread_Pool {
  9. public:
  10.     classTask{
  11.       //这个地方就是想要Task的集合,这样写有什么不妥吗?
  12.        //TODO:有没有较为好点的写法
  13.        friend classThread_Pool;
  14.    public:
  15.       Task(){}
  16.        virtual~Task(){}
  17.    private:
  18.        void(*function)(void *);//函数指针
  19.        void*argument;//传进函数的这个参数
  20.    };
  21.    Thread_Pool();
  22.    virtual ~Thread_Pool();
  23.     voidThread_Pool_init(int thread_count_in_pool_,inttask_count_in_queue_);
  24.     voidThread_Pool_add(void (*function_)(void *), void*argument_);
  25.    static void * threadpool_thread(void *arg);
  26. private:
  27.    pthread_mutex_t lock;
  28.    pthread_cond_t notify;
  29.    pthread_t *thread_id_list;
  30.    std::vector<Task*>task_list;
  31.     intthread_count_in_pool;//线程池里面总共有多少个线程
  32.     inttask_count_in_queue;//任务队列中的任务个数
  33.     inthead_in_queue;//先插进queue的任务
  34.     inttail_in_queue;//后插进queue的任务
  35.    //以上两个参数其实是任务的索引,是FIFO的
  36.     intpending_task_count;//在等待执行的任务
  37.     intstarted_thread_count;//已经开始运行的线程,create之后知道exit的线程个数
  38. };
  39. #endif

.cpp文件:
  1. #include "Thread_Pool.h"
  2. Thread_Pool::Thread_Pool() {
  3.     //TODO 自动生成的构造函数存根
  4. }
  5. Thread_Pool::~Thread_Pool() {
  6.     //TODO 自动生成的析构函数存根
  7. }
  8. void Thread_Pool::Thread_Pool_init(intthread_count_in_pool_,int task_count_in_queue_){
  9.    //这里第二个参数为NULL的原因是参数不用设置
  10.    pthread_mutex_init(&lock,NULL);
  11.    pthread_cond_init(&notify,NULL);
  12.    thread_id_list=(pthread_t*)malloc(sizeof(pthread_t)*thread_count_in_pool_);
  13.    for(int i=0;i<task_count_in_queue_;i++){
  14.        Task*task=new Thread_Pool::Task();
  15.       task_list.push_back(task);
  16.    }
  17.    thread_count_in_pool=0;
  18.    task_count_in_queue=task_count_in_queue_;
  19.    head_in_queue=tail_in_queue=0;
  20.    pending_task_count=0;
  21.    started_thread_count=0;
  22.    for(int i=0;i<thread_count_in_pool_;i++){
  23.       //这里的一定要搞清楚,因为传递的是本实例的指针
  24.       pthread_create(&thread_id_list[i],NULL,threadpool_thread,this);
  25.       thread_count_in_pool++;
  26.       //因为一创建线程就开始做了,所以要把开始做的线程加1
  27.       started_thread_count++;
  28.    }
  29. }
  30. void Thread_Pool::Thread_Pool_add(void (*function_)(void *),void *argument_){
  31.     intnext_task_todo=0;
  32.    pthread_mutex_lock(&lock);
  33.    next_task_todo=tail_in_queue+1;
  34.    next_task_todo=(next_task_todo==task_count_in_queue)?0:next_task_todo;
  35.    do{
  36.       if(pending_task_count==task_count_in_queue)
  37.          break;
  38.       task_list[tail_in_queue]->function=function_;
  39.       task_list[tail_in_queue]->argument=argument_;
  40.       tail_in_queue=next_task_todo;
  41.       pending_task_count++;
  42.       pthread_cond_signal(&notify);
  43.    }while(0);
  44.    pthread_mutex_unlock(&lock);
  45. }
  46. void *Thread_Pool::threadpool_thread(void *arg){
  47.    Thread_Pool *Pthis=(Thread_Pool*)arg;
  48.     Task*task=new Task();
  49.    //这是线程池创建的一个程序块,这里其实是一个for循环,一直在等待add函数添加一个函数去给执行
  50.    while(1){
  51. //      cout<<">>>>>>herein thread "<<endl;
  52.       pthread_mutex_lock(&(Pthis->lock));
  53. //      cout<<">>>>>>herein thread, pass thelock"<<endl;
  54.       //如果还没有一个任务到来的话,证明进入这个锁之后的任务是第一个创建之后还没有得到得到任务的那个线程,
  55.       //这样的话就一直循环等待,当没有任务的时候你肯定要等待,不然你拿什么去做,但是这个地方一定要这个循环吗?
  56.       while(Pthis->pending_task_count==0){
  57.          pthread_cond_wait(&(Pthis->notify),&(Pthis->lock));
  58.        }
  59.       task->function=Pthis->task_list.at(Pthis->head_in_queue)->function;
  60.       task->argument=Pthis->task_list.at(Pthis->head_in_queue)->argument;
  61.       Pthis->head_in_queue=Pthis->head_in_queue+1;
  62.       //这里是一个循环使用task队列,如果满了计数就从头开始,有bug
  63.        //TODO:解决对面追上前面怎么办?会出现这样的情况吗?
  64.       Pthis->head_in_queue=(Pthis->head_in_queue==Pthis->task_count_in_queue)?0:Pthis->head_in_queue;
  65.       Pthis->pending_task_count=Pthis->pending_task_count-1;
  66.       pthread_mutex_unlock(&(Pthis->lock));
  67.       (*(task->function))(task->argument);
  68.    }
  69.    Pthis->started_thread_count=Pthis->started_thread_count-1;
  70.    pthread_mutex_unlock(&(Pthis->lock));
  71.    pthread_exit(NULL);
  72.    return (NULL);
  73. }
task函数:
  1. void dummy_task(void *arg) {
  2.    usleep(10000);
  3.    pthread_mutex_lock(&lock_);
  4.    sleep(1);
  5.    printf("I am doing my work, use seconds!\n");
  6.    pthread_mutex_unlock(&lock_);
  7. }
测试代码:
  1. pthread_mutex_init(&lock_,NULL);
  2. Thread_Pool *tp=new Thread_Pool();
  3. tp->Thread_Pool_init(10,5);
  4. tp->Thread_Pool_add(dummy_task,tp);
  5. tp->Thread_Pool_add(dummy_task,tp);
  6. tp->Thread_Pool_add(dummy_task,tp);
  7. tp->Thread_Pool_add(dummy_task,tp);
  8. tp->Thread_Pool_add(dummy_task,tp);

3,高级线程池
/* * ThreadPool.cpp * *  Created on: 2014-8-20 *      Author: casa */#include "ThreadPool.h"ThreadPool::ThreadPool(int nthreads,int capacity):nthreads_(nthreads),queue_(new CircleQueue<Task>(capacity)) {// TODO Auto-generated constructor stub}ThreadPool::~ThreadPool() {// TODO Auto-generated destructor stubdelete queue_;}void *ThreadPool::single_thread(void *args) {ThreadPool *tp=reinterpret_cast<ThreadPool *>(args);while(true){pthread_mutex_lock(&(tp->lock_));if(tp->queue_->empty()==true){cout<<"I am waiting!"<<endl;pthread_cond_wait(&(tp->condition_),&(tp->lock_));}/* if not emtpy in task pool, a task can be done here! */Task *task=tp->queue_->pop();pthread_mutex_unlock(&(tp->lock_));task->run();}/* TODO: how to terminate the single thread. */return 0;}void ThreadPool::init_thread_pool() {pthread_mutex_init(&lock_,0);pthread_cond_init(&condition_,0);pthread_t *threads_array=new pthread_t[nthreads_];for(unsigned i=0;i<nthreads_;i++){pthread_create(&threads_array[i],0,single_thread,this);}}void ThreadPool::destroy_thread_pool() {}void ThreadPool::add_into_thread_pool(void (*func)(void *), void *args) {Task *task=new Task(func,args);pthread_mutex_lock(&lock_);while(true){if(queue_->push(task)==true){pthread_cond_signal(&condition_);break;}else{/*TODO: ugly code, when full, it will waste CPU in while loop */continue;}}pthread_mutex_unlock(&lock_);}

/* * ThreadPool.h * *  Created on: 2014-8-20 *      Author: casa */#ifndef THREADPOOL_H_#define THREADPOOL_H_#include "CircleList.h"#include "SmartPtr.h"#include "Task.h"#include <pthread.h>class ThreadPool {public:ThreadPool(int nthreads, int capacity);virtual ~ThreadPool();static void* single_thread(void * args);void add_into_thread_pool(void (*func)(void *args), void *args);void init_thread_pool();void destroy_thread_pool();private:int nthreads_;pthread_mutex_t lock_;pthread_cond_t condition_;CircleQueue<Task> *queue_;};#endif /* THREADPOOL_H_ */


增加中...