简易线程池的实现

1 线程池

为了避免多线程操作过程种线程频繁申请和释放所带来的性能消耗,可以提前创建多个线程,当有任务到来时从线程池中选择一个线程执行,执行完后继续在线程池中待命。

核心是使用一个工作队列,主线程往工作队列中添加工作,工作线程从队列中取出工作并执行。

对工作队列的操作就是经典的生产者—消费者模型,需要用到互斥锁和条件变量。

 

2 工作定义

通过函数指针指向执行函数。

typedef struct Task{
    void (*func)(void* arg);
    void* arg;
}Task;

  

3 线程池定义

使用 list 容器来存储工作,定义工作队列的最大数 m_max_requests 和 线程总数 m_max_threads。在对工作队列操作时需要用到互斥锁 m_mutex_pool,条件变量 m_notfull 和 m_notempty。

class ThreadPool{
public:
    ThreadPool(int m_max_threads, int m_max_requests);
    ~ThreadPool();
    bool addWork(void(*func)(void*), void* arg);

private:
    static void* worker(void* arg);
    void run();

private:
    std::list<Task*> m_workqueue;  /*工作队列*/
    int m_max_requests;  /*请求队列中允许的最大请求数*/
    int m_max_threads;  /*线程总数*/

    pthread_t* m_worker_threads;  /*工作线程*/

    pthread_mutex_t m_mutex_pool;

    pthread_cond_t m_notfull;
    pthread_cond_t m_notempty;

    bool m_stop;
};


ThreadPool::ThreadPool(int m_max_threads, int m_max_requests):
        m_max_threads(m_max_threads), m_max_requests(m_max_requests), m_stop(false){
    
    if(m_max_threads <= 0 || m_max_requests <= 0){
        throw std::exception();
    }
    
    /*创建线程池*/
    m_worker_threads = new pthread_t[m_max_threads];
    if(!m_worker_threads){
        throw std::exception();
    }
    //memset(m_worker_threads, 0, sizeof(m_worker_threads));

    /*初始化互斥锁、条件变量*/
    if(0 != pthread_mutex_init(&m_mutex_pool, NULL) ||
       0 != pthread_cond_init(&m_notfull, NULL) ||
       0 != pthread_cond_init(&m_notempty, NULL)){
           throw std::exception();
       } 
    

    /*创建工作线程*/
    for(int i=0; i<m_max_threads; ++i){
        printf("Create the %dth thread\n", i);
        if(0 != pthread_create(&m_worker_threads[i], 0, worker, this)){
            delete []m_worker_threads;
            throw std::exception();
        };

        if(pthread_detach(m_worker_threads[i])){
            delete [] m_worker_threads;
            throw std::exception();
        }
    }
}


ThreadPool::~ThreadPool(){
    delete []m_worker_threads;
    m_stop = true;
}


bool ThreadPool::addWork(void(*func)(void*), void* arg){
    pthread_mutex_lock(&m_mutex_pool);
    while(!m_stop && m_workqueue.size() >= m_max_requests){
        pthread_cond_wait(&m_notfull, &m_mutex_pool);
    }
    if(m_stop){
        pthread_mutex_unlock(&m_mutex_pool);
        return false;
    }

    /*添加工作*/
    Task* task = new Task;
    task->func = func;
    task->arg = arg;
    m_workqueue.push_back(task);

    pthread_mutex_unlock(&m_mutex_pool);
    pthread_cond_signal(&m_notempty);
    
    return true;
}


void* ThreadPool::worker(void* arg){
    ThreadPool* pool = (ThreadPool*)arg;
    pool->run();
    return pool;
}

void ThreadPool::run(){
    while(1){
        pthread_mutex_lock(&m_mutex_pool);
        while(m_workqueue.empty() && !m_stop){
            pthread_cond_wait(&m_notempty, &m_mutex_pool);
        }

        /*从工作队列中取任务*/
        Task* task = m_workqueue.front();
        m_workqueue.pop_front();

        pthread_mutex_unlock(&m_mutex_pool);
        pthread_cond_signal(&m_notfull);

        printf("Thread %ld start working...\n", pthread_self());

        /*执行任务*/
        task->func(task->arg);
        delete task;

        printf("Thread %ld end working...\n", pthread_self());

    }
}


#endif

  

4 测试代码

#include "threadpool.h"
#include<iostream>
#include<unistd.h>
using namespace std;

void taskFunc(void* arg)
{
    int num = *(int*)arg;
    printf("Thread %ld is working, number = %d\n", pthread_self(), num);
    sleep(1);
}


int main(){
    ThreadPool* pool = new ThreadPool(10, 20);
    for (int i = 0; i < 100; ++i)
    {
        int* num = (int*)malloc(sizeof(int));
        *num = i;
        pool->addWork(taskFunc, num);
    }

    sleep(30);

    return 0;
}

 

 

References:

  1. 手写线程池 - C 语言版
  2. 《Linux高性能服务器编程》
posted @ 2022-04-20 09:49  Kayden_Cheung  阅读(62)  评论(0编辑  收藏  举报
//目录