线程池简单实现(C++11/C99)

文章目录

  • 一、基于C++11的线程池实现
  • 二、基于C99的线程池实现


一、基于C++11的线程池实现

#ifndef THREAD_POOL_HPP
#define THREAD_POOL_HPP

#include 
#include 
#include 
#include 

#include 

#define THREAD_MAX_NUM 3 // 线程池最大线程数

using namespace std;

class ThreadPool {
private:
    bool m_open_flag;                     // 表示线程池运行标志,用于线程回收
    int m_thread_count;                   // 线程池中剩余线程数,用于检测线程退出

    mutex m_mutex_run;                    // 用于线程运行时互斥,主要是互斥操作任务队列
    mutex m_mutex_quit;                   // 用于线程退出时互斥
    condition_variable m_cond_run;        // 用于线程间运行时同步
    condition_variable m_cond_quit;       // 用于线程间退出时同步

    queue<function<void()>> m_task_queue; // 线程池任务队列

public:
    explicit ThreadPool(int thread_count = THREAD_MAX_NUM) {
        assert(thread_count > 0);

        m_open_flag = true;
        m_thread_count = thread_count;

        for (int i = 0; i < thread_count; i++) {
            /* 通过匿名函数依次创建子线程 */
            thread([this] {
                unique_lock<mutex> locker(m_mutex_run); // 互斥操作任务队列
                while (true) {
                    if (!m_task_queue.empty()) {
                        auto task = std::move(m_task_queue.front()); // 通过move将任务函数转换为右值引用,提高传递效率
                        m_task_queue.pop();
                        locker.unlock(); // 把锁释放,避免自己的业务处理影响其他线程的正常执行
                        task(); // 执行任务队列中的任务函数
                        locker.lock(); // 重新获取锁
                    } else if (!m_open_flag) {
                        m_thread_count--;
                        if (m_thread_count == 0) {
                            m_cond_quit.notify_one(); // 所有子线程均已退出,通知主线程退出
                        }
                        break;
                    } else {
                        m_cond_run.wait(locker); // 阻塞等待 m_mutex_run
                    }
                }
            }).detach();
        }
    }

    ~ThreadPool() {
        {
            unique_lock<mutex> locker(m_mutex_run); // 互斥操作m_open_flag
            m_open_flag = false;
        }
        m_cond_run.notify_all(); // 通知线程队列中的所有子线程退出
        {
            unique_lock<mutex> locker(m_mutex_quit);
            m_cond_quit.wait(locker); // 阻塞等待m_mutex_quit,会由最后一个退出的子线程通知
        }
    }

    template<class T>
    void addTask(T &&task) {
        {
            unique_lock<mutex> locker(m_mutex_run); // 互斥操作任务队列
            m_task_queue.emplace(std::forward<T>(task)); // 通过完美转发传递任务函数
        }
        m_cond_run.notify_one(); // 通知线程队列中的首子线程执行任务
    }
};

void threadFun(int x) {
    cout << x << endl;
}

int main() {
    ThreadPool thread_pool;

    for (int i = 0; i < 10; i++) {
        thread_pool.addTask(bind(threadFun, i)); // 通过bind绑定参数
    }
}

#endif
atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main                             
0
3
4
5
6
7
8
9
2
1
atreus@MacBook-Pro % 

二、基于C99的线程池实现

#include 
#include 

#include 
#include 

#define THREAD_MAX_NUM 3 // 线程池最大线程数
#define TASK_MAX_NUM 10  // 任务队列最大任务数

/* 任务队列结构体定义 */
typedef struct task_t {
    void *(*fun)(void *arg); // 指向作业函数的指针,该函数返回一个void型指针
    void *arg;               // 指向作业函数的参数的指针
    struct task_t *next;     // 指向作业队列中的下一个作业的指针
} task_t, *task_queue_t;

/* 线程池结构体定义 */
typedef struct thread_pool_t {
    pthread_t *thread_id_list; // 线程池中所有线程的id

    int task_cur_num;        // 任务队列当前长度
    task_t *task_queue_head; // 任务队列头指针
    task_t *task_queue_tail; // 任务队列尾指针

    pthread_mutex_t mutex;               // 用于保证各个线程互斥访问线程池的互斥锁
    pthread_cond_t task_queue_empty;     // 任务队列空
    pthread_cond_t task_queue_not_empty; // 任务队列不空
    pthread_cond_t task_queue_not_full;  // 任务队列不满
} thread_pool_t;

/**
 * @brief 初始化线程池
 * @param thread_pool 线程池指针的地址
 */
void thread_pool_init(thread_pool_t **thread_pool);

/**
 * @brief 销毁线程池
 * @param thread_pool 线程池指针
 */
void thread_pool_destroy(thread_pool_t *thread_pool);

/**
 * @brief 向线程池中添加任务
 * @param thread_pool 线程池指针
 * @param fun 交给此任务执行的函数指针
 * @param arg 上述函数的参数
 */
void thread_pool_add_task(thread_pool_t *thread_pool, void *(*fun)(void *), void *arg);

/**
 * @brief 线程池中线程的运行函数
 * @param arg 线程池中线程的参数,主要是线程所属线程池
 * @return void* 返回值
 */
void *thread_pool_execute(void *arg);

void *thread_fun(void *arg) {
    printf("%d\n", *(int *) arg);
    return NULL;
}

int main() {
    thread_pool_t *thread_pool;

    thread_pool_init(&thread_pool);

    int arg[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    for (int i = 0; i < 10; i++) {
        thread_pool_add_task(thread_pool, thread_fun, (void *) (arg + i));
    }

    thread_pool_destroy(thread_pool);
}

void thread_pool_init(thread_pool_t **pool) {
    *pool = (thread_pool_t *) calloc(1, sizeof(thread_pool_t));

    /* 初始化线程池线程线程列表 */
    (*pool)->thread_id_list = (pthread_t *) calloc(THREAD_MAX_NUM, sizeof(pthread_t));

    /* 初始化任务队列 */
    (*pool)->task_cur_num = 0;
    (*pool)->task_queue_head = (*pool)->task_queue_tail = NULL;

    /* 初始化互斥锁和条件变量 */
    pthread_mutex_init(&((*pool)->mutex), NULL);
    pthread_cond_init(&((*pool)->task_queue_empty), NULL);
    pthread_cond_init(&((*pool)->task_queue_not_empty), NULL);
    pthread_cond_init(&((*pool)->task_queue_not_full), NULL);

    /* 创建线程 */
    for (int i = 0; i < THREAD_MAX_NUM; i++) {
        pthread_create((*pool)->thread_id_list + i, NULL, thread_pool_execute, (void *) *pool);
    }

    printf("Threadpoll initialized successfully. [thread_pool.c]\n");
}

void thread_pool_destroy(thread_pool_t *pool) {
    pthread_mutex_lock(&pool->mutex);

    while (pool->task_cur_num != 0) { // 等待所有的任务被处理完毕
        pthread_cond_wait(&pool->task_queue_empty, &pool->mutex);
    }
    pool->task_cur_num = -1; // 通知所有线程结束运行

    pthread_mutex_unlock(&pool->mutex);

    pthread_cond_broadcast(&pool->task_queue_not_empty); // 唤醒所有因为任务队列空而阻塞的线程
    for (int i = 0; i < THREAD_MAX_NUM; i++) {
        pthread_join(pool->thread_id_list[i], NULL);
    }
    pthread_mutex_destroy(&pool->mutex);
    pthread_cond_destroy(&pool->task_queue_empty);
    pthread_cond_destroy(&pool->task_queue_not_empty);
    pthread_cond_destroy(&pool->task_queue_not_full);

    printf("Threadpoll was successfully destroyed. [thread_pool.c]\n");
}

void thread_pool_add_task(thread_pool_t *pool, void *(*fun)(void *), void *arg) {
    task_t *new_task = (task_t *) calloc(1, sizeof(task_t));

    pthread_mutex_lock(&pool->mutex); // 互斥访问线程池

    while (pool->task_cur_num == TASK_MAX_NUM) { // 任务队列满
        pthread_cond_wait(&pool->task_queue_not_full, &pool->mutex);
    }

    /* 初始化新的任务节点 */
    new_task->fun = fun;
    new_task->arg = arg;
    new_task->next = NULL;

    /* 向线程池的任务队列中添加新任务 */
    if (pool->task_queue_head == NULL) { // 任务队列空
        pool->task_queue_head = pool->task_queue_tail = new_task; // 添加新的任务
        pthread_cond_broadcast(&pool->task_queue_not_empty); // 唤醒因为任务队列空而阻塞的线程
    } else {
        pool->task_queue_tail->next = new_task; // 添加新的任务
        pool->task_queue_tail = new_task; // 移动任务队列尾指针
    }
    pool->task_cur_num++; // 任务数量加一

    pthread_mutex_unlock(&pool->mutex);
}

void *thread_pool_execute(void *arg) {
    thread_pool_t *pool = (thread_pool_t *) arg; // 通过参数获取自己所属的线程池
    task_t *task = NULL;

    while (1) {
        pthread_mutex_lock(&pool->mutex); // 互斥访问线程池
        while (pool->task_cur_num == 0) { // 任务队列空
            pthread_cond_wait(&pool->task_queue_not_empty, &pool->mutex);
        }
        if (pool->task_cur_num == -1) {
            pthread_mutex_unlock(&pool->mutex);
            pthread_exit(NULL);
        }
        task = pool->task_queue_head; // 取出任务队列中的首个任务
        pool->task_cur_num--; // 任务队列任务数减一
        pthread_cond_broadcast(&pool->task_queue_not_full); // 继续向任务队列添加任务

        if (pool->task_cur_num == 0) { // 任务队列空
            pool->task_queue_head = pool->task_queue_tail = NULL;
            pthread_cond_broadcast(&pool->task_queue_empty);
        } else {
            pool->task_queue_head = pool->task_queue_head->next;
        }

        pthread_mutex_unlock(&pool->mutex);

        (*task->fun)(task->arg); // 执行所取出的任务的函数

        free(task); // 释放内存
        task = NULL; // 避免悬空指针
    }
}
atreus@MacBook-Pro % clang main.c -o main
atreus@MacBook-Pro % ./main              
Threadpoll initialized successfully. [thread_pool.c]
1
4
5
6
7
8
9
0
2
3
Threadpoll was successfully destroyed. [thread_pool.c]
atreus@MacBook-Pro % 

你可能感兴趣的:(C/C++,Linux,c++,开发语言,c语言)