threadpool.h

#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <pthread.h> // 导入线程池头文件
#include <list> // 请求队列
#include "locker.h" // 自己写的互斥锁
#include <exception> // 异常throw std::exception();
#include <cstdio>


// 线程池: 找个线程处理任务
// 定义成模板类为了代码的复用,在别的项目中也能用
// 模板参数T是任务类
// 5.5 34:08

// 模板类T唯一需要具有的函数  process()
template<typename T>
class threadpool{
public:
    threadpool(int thread_number = 8, int max_requests = 10000); //构造函数
    ~threadpool();  // 析构函数
    bool append(T* request);

private:
    static void * worker(void * arg); // 静态的函数,子线程执行的内容,pthread_create中子线程执行的内容
    void run();

private:
    int m_thread_number;// 线程的数量
    pthread_t * m_threads;// 容器装线程:线程池数组,大小为m_thread_number
    int m_max_requests; // 请求队列中最多允许的等待处理的请求数量
    std::list<T *> m_workqueue; // 请求队列
    locker m_queuelocker;// 互斥锁
    sem m_queuestat;// 信号量:用来判断是否有任务需要处理
    bool m_stop;// 是否结束线程
};

// 成员函数的实现
// 构造函数
template<typename T>
threadpool<T>::threadpool(int thread_number, int max_requests) :   // 单冒号,对成员初始化
    m_thread_number(thread_number), m_max_requests(max_requests),
    m_stop(false),m_threads(NULL){
    if(thread_number <= 0 || max_requests <= 0){
        throw std::exception();
    }
    m_threads = new pthread_t[m_thread_number];  // 创建m_thread_number个线程,是一个数组
    if(!m_threads){
        throw std::exception();
    }
    // 创建thread_number个线程,并将他们设置为线程脱离。
    // 线程脱离,自动释放线程
    for(int i = 0; i < thread_number; ++i){
        printf("create the %dth thread\n", i);   // #include <cstdio.h>
        // pthread_create 如果成功了结果返回 0 ,否则非0,可能是状态码
        if(pthread_create(m_threads + i, NULL, worker, this) !=0){ // worker是个子线程执行的内容,是一个静态函数,this 传递给worker,worker内就可以使用该对象的成员,如果没有this,
                                                                    // 因为worker是静态的,无法使用该对象的成员。  
            delete[] m_threads;  // 使用new[] 创建,那么需要使用delete[] 删除
            throw std::exception();
        }
        // 线程分离:设置线程的一种属性,如果该线程执行完毕,那么自动释放该线程的资源
        if(pthread_detach(m_threads[i])){
            delete[] m_threads;
            throw std::exception();
        }
    }
}

// 析构函数
template<typename T>
threadpool<T>::~threadpool(){
    delete[] m_threads;
    m_stop = true; // 停止线程
}

// append函数
template<typename T>
bool threadpool<T>::append(T * request){  // 需要写返回值类型
    m_queuelocker.lock(); // 上锁
    // 超过最大量
    if(m_workqueue.size() > m_max_requests){
        m_queuelocker.unlock();
        return false;
    }

    m_workqueue.push_back(request);
    m_queuelocker.unlock(); // 解锁
    m_queuestat.post(); // 队列中增加,信号量增加。根据信号量判断阻塞or执行
    return true;
}

// worker函数
template<typename T>
void* threadpool<T>::worker(void * arg){
    threadpool * pool = (threadpool *) arg;
    pool->run();
    return pool;
}

// run函数
template<typename T>
void threadpool<T>::run(){
    while(!m_stop){ // run() 一直要执行,直到遇到停止信号
        m_queuestat.wait(); // 信号量调用wait();没有值堵在这
        m_queuelocker.lock(); // 上锁
        if(m_workqueue.empty()){  // 如果空的那么continue到while开始。再次检测
            m_queuelocker.unlock();
            continue;
        }

        // 有数据
        T * request = m_workqueue.front(); // 取出第一个
        m_workqueue.pop_front(); // 删除取出来的那个
        m_queuelocker.unlock(); // 解锁以后才能操作
        if(! request){
            continue;
        }

        request->process(); // 处理任务  // 模板类T唯一需要具有的函数  process()
    }
}
#endif
posted @ 2022-01-14 09:14  子于舟  阅读(300)  评论(1)    收藏  举报