• 简易线程池的实现


    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高性能服务器编程》
  • 相关阅读:
    11种常用css样式之background学习
    11种常用css样式之开篇文本字体学习
    学习css常用基本层级伪类属性选择器
    学习了解CSS3发展方向和CSS样式与优先级
    常见CSS3选择器和文本字体样式汇总
    简单了解css3样式表写法和优先级
    4——PHP比较&&复制运算符
    虚基类
    string类中getline函数的应用
    string类应用举例
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/16168569.html
Copyright © 2020-2023  润新知