线程池

一、线程池功能组件

总共包含三个组件:线程池、线程执行任务,任务详情。

线程池包含条件等待,锁,链中线程任务某一个,链中job队列中某一个。

线程执行任务包含线程池,当前线程,当前线程的的prev和next。

任务详情包含回调函数,回调函数的参数,当前job的prev和next。

二、代码编写流程

  1. 初始化线程池:ThreadPool pool
  2. 为线程池添加线程:参数是线程池指针,线程数量
    2.1 如果线程数量小于1,赋值1
    2.2 为线程池pool分配内存空间
    2.3 创建条件信号量,将条件信号量赋值给线程池的条件信号量
    2.4 创建锁,将锁赋值给线程池的锁
    2.5 遍历线程数量,生成执行任务的结构体,并分配内存空间,同时初始化执行任务结构体
    2.6 创建线程pthread_create(&worker->thread,NULL,ntyWorkThread,(void*)worker),将其指针给执行任务的线程,并且执行的方法是线程执行任务的方法,worker是线程方法的参数。通过worker的线程池的等待任务队列中,获取对应的job回调函数和回调函数的参数,并执行任务的回调函数,释放worker,线程退出
  3. 为线程池添加任务: 参数是线程池指针,和job结构体
    3.1 加锁
    3.2 将线程池添加job
  4. 关闭线程池
    4.1 遍历线程池,将所有执行线程设置终止条件设置为1
    4.2 加锁
    4.3 将线程池的当前work设置为NULL
    4.4 线程池的等待队列job设置为NULL
    4.5 广播信号量
    4.6 解锁

main的执行顺序

  1. 初始化线程池结构体
  2. 初始化线程池
  3. 添加job
  4. 关闭线程池

三、具体代码

//
// Created by rosy on 2022/7/24.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#define MAX_NUM_THREADS  100
#define NUM_JOBS  1000

#define LL_ADD(item,list) do{ \
    item->prev = NULL; \
    item->next = list; \
    list = item; \
} while(0)

#define LL_REMOVE(item,list) do { \
    if(item->prev != NULL) item->prev->next = item->next; \
    if(item->next != NULL) item->next->prev = item->prev; \
    if(list == item) list = item->next;                   \
    item->prev = item->next = NULL ;\
} while(0)


typedef struct NWORK{
    pthread_t thread;
    struct THREAD_POOL *thread_pool;
    struct NWORK *prev;
    struct NWORK *next;
    int terminate;
} nWork;

typedef struct THREAD_POOL{
    pthread_cond_t job_cond;
    pthread_mutex_t  job_mtx;
    struct NWORK *works;
    struct NJOB *jobs;

} thread_pool;

typedef struct NJOB{
    void (*job_function)(struct NJOB *job);
    void *user_data;
    struct NJOB *prev;
    struct NJOB *next;
} nJob;

static void *work_do_job(void *ptr){
    nWork  *work = (nWork*)ptr;

    while(1) {
        pthread_mutex_lock(&work->thread_pool->job_mtx);

        while(work->thread_pool->jobs == NULL){
            if(work->terminate){
                break;
            }

            pthread_cond_wait(&work->thread_pool->job_cond,&work->thread_pool->job_mtx);
        }

        if(work->terminate){
            pthread_mutex_unlock(&work->thread_pool->job_mtx);
            break;

        }

        nJob *job = work->thread_pool->jobs;
        if(job != NULL){ //移除当前job
            LL_REMOVE(job,work->thread_pool->jobs);
        }

        pthread_mutex_unlock(&work->thread_pool->job_mtx);

        if(job == NULL) continue;

        job->job_function(job);
    }

    free(work);
    pthread_exit(NULL);
}

int createThreadPool(thread_pool* pool,int num_works){

    if(num_works < 1) {
        num_works = 1;
    }
    memset(pool,0,sizeof(thread_pool));

    pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;
    memcpy(&pool->job_cond,&blank_cond,sizeof(pool->job_cond));

    pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER;
    memcpy(&pool->job_mtx,&blank_mutex,sizeof(pool->job_mtx));

    for(int i = 0; i < num_works;i++){
        nWork *work = (nWork*)malloc(sizeof(nWork));
        if(work == NULL){
            perror("malloc work");
            return 1;
        }
        memset(work,0,sizeof(nWork));

        work->thread_pool = pool;

        int ret = pthread_create(&work->thread,NULL,work_do_job,(void *)work);
        if(ret){
            perror("pthread_create");
            free(work);
            return 1;
        }
        LL_ADD(work,work->thread_pool->works);
    }
    return 0;
}

void add_job(thread_pool *pool,nJob* job){

    pthread_mutex_lock(&pool->job_mtx);

    LL_ADD(job,pool->jobs);

    pthread_cond_signal(&pool->job_cond);
    pthread_mutex_unlock(&pool->job_mtx);


}

void shut_down(thread_pool *pool){
    nWork *work = NULL;
    for(work = pool->works; work != NULL; work = work->next){
        work->terminate = 1;
    }

    pthread_mutex_lock(&pool->job_mtx);

    pool->works = NULL;
    pool->jobs = NULL;

    pthread_cond_broadcast(&pool->job_cond);
    pthread_mutex_unlock(&pool->job_mtx);
}

void counter(nJob *job){
    int index = *(int*)job->user_data;

    printf("index:%d,selfid:%lu\n",index,pthread_self());

    free(job->user_data);
    free(job);
}

int main(int argc,char *argv[]) {
    printf("hello yes\n");
    thread_pool pool;
    createThreadPool(&pool,MAX_NUM_THREADS);

    printf("create thread pool\n");
    for(int i = 0; i < NUM_JOBS; i++){
        nJob *job = (nJob*)malloc(sizeof(nJob));
        if(job == NULL){
            perror("malloc");
            exit(1);
        }

        job->job_function = counter;
        job->user_data = malloc(sizeof(int));
        *(int*)job->user_data = i;

        add_job(&pool,job);
    }
    printf("关闭...\n");
    shut_down(&pool);

    getchar();
    printf("finish\n");

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容