一个通用简单线程池实现的初步封装(C语言)

概述:之前总是听别人说线程池,一直没接触过,借业余时间学习了一下,现在自己简单的封装了一下,也只是在学习的层面,用到实际操作可能还需很多优化修改。

1,先看封装的结构体吧,sky_pool.h文件内容,主要就是定义封装了一下线程池所需用到的参数等。

#ifndef _SKY_POOL_H_
#define _SKY_POOL_H_

#include <stdint.h>
#include <pthread.h>

typedef struct worker worker_t;
typedef struct thread_pool thread_pool_t;
typedef struct tpool_ctl tpool_ctl_t;

typedef void (*thread_cb_t)(void *arg);

struct worker {
    thread_cb_t cb;         /*任务回调函数*/
    void *arg;              /*回调函数参数*/
    worker_t *next;
};

struct thread_pool {
    pthread_mutex_t work_lock;  
    pthread_cond_t work_cond;
    pthread_t *thread_id;

    uint8_t pool_destory;       /*线程池销毁标志*/
    uint32_t thread_num;        /*初始创建线程数目*/
    uint32_t worklist_size;     /*当前任务数目*/

    worker_t *worklist;    /*具体需要执行的任务链表*/
};

typedef void (*tpool_addwork_t)(tpool_ctl_t *, thread_cb_t , void *);
typedef void (*tpool_destory_t)(tpool_ctl_t *);

struct tpool_ctl {
    struct thread_pool tp;     /*线程池结构*/
    tpool_addwork_t add;
    tpool_destory_t del;
};

tpool_ctl_t *tpctl_create(uint32_t thread_num);


#endif

2,接下来就是一个sky_pool.c文件,主要是实现线程池的创建,初始化,任务添加等。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
#include "sky_pool.h"

/*互斥锁加锁解锁封装*/
static void tpctl_lock(tpool_ctl_t *tpctl)
{
    pthread_mutex_lock(&(tpctl->tp.work_lock));
}

static void tpctl_unlock(tpool_ctl_t *tpctl)
{
    pthread_mutex_unlock(&(tpctl->tp.work_lock));
}

/*线程入口函数*/
static void *thread_runing(void *arg)
{
    tpool_ctl_t *tpctl = arg;
    printf ("starting thread %08x\n", pthread_self ());
    while (1) {
        tpctl_lock(tpctl);
        while (!tpctl->tp.pool_destory && 0 == tpctl->tp.worklist_size) {
            /*无任务且不执行线程池销毁操作,线程阻塞等待*/
            printf("thread %08x waiting...\n",pthread_self ());
            pthread_cond_wait(&(tpctl->tp.work_cond), &(tpctl->tp.work_lock));
        }
        /*判断是否销毁线程*/
        if (tpctl->tp.pool_destory) {
            tpctl_unlock(tpctl);
            printf("thread %08x exit...\n",pthread_self ());
            pthread_exit(NULL);
        }
        assert(tpctl->tp.worklist != NULL);
        assert(tpctl->tp.worklist_size != 0);
        if (NULL != tpctl->tp.worklist && tpctl->tp.worklist_size > 0) {
            /*取出任务*/
            tpctl->tp.worklist_size --;
            worker_t *current_work = tpctl->tp.worklist;
            tpctl->tp.worklist = current_work->next;
            tpctl_unlock(tpctl);
            /*回调函数,执行任务*/
            printf ("thread %08x work...\n", pthread_self ());
            current_work->cb(current_work->arg);
            free(current_work);
            current_work = NULL;
        }
    }
}

/*添加任务到工作链表*/
static void tpool_addworker(tpool_ctl_t *tpctl, thread_cb_t cb, void *arg)
{
    worker_t *new_work = (worker_t *)malloc(sizeof(worker_t));
    new_work->cb = cb;
    new_work->arg = arg;
    new_work->next = NULL;
    tpctl_lock(tpctl);
    worker_t *worklist = tpctl->tp.worklist;
    if (NULL != worklist) {
        while (NULL != worklist->next) {
            worklist = worklist->next;
        }
        worklist->next = new_work;
    } else {
        tpctl->tp.worklist = new_work;
    }
    tpctl->tp.worklist_size ++;
    tpctl_unlock(tpctl);
    /*发送信号,唤醒某个线程执行任务*/
    pthread_cond_signal(&(tpctl->tp.work_cond));
}

/*线程池销毁*/
static void tpool_destory(tpool_ctl_t *tpctl)
{
    if (tpctl->tp.pool_destory) {
        return ;
    }
    tpctl->tp.pool_destory = 1;

    pthread_cond_broadcast (&(tpctl->tp.work_cond));
    /*销毁线程*/
    uint32_t i;
    for (i = 0 ; i < tpctl->tp.thread_num ; i ++) {
        pthread_join(tpctl->tp.thread_id[i],NULL);
    }
    free(tpctl->tp.thread_id);
    /*销毁任务链表*/
    worker_t *work = NULL;
    while (NULL != tpctl->tp.worklist) {
        work = tpctl->tp.worklist;
        tpctl->tp.worklist = tpctl->tp.worklist->next;
        free(work);
    }
    /*互斥锁销毁*/
    pthread_mutex_destroy(&(tpctl->tp.work_lock));
    pthread_cond_destroy(&(tpctl->tp.work_cond));

    free(tpctl);
    tpctl = NULL;
}

/*线程池的初始化*/
static void tpctl_init(tpool_ctl_t *tpctl, uint32_t thread_num)
{
    pthread_mutex_init(&(tpctl->tp.work_lock),NULL);
    pthread_cond_init(&(tpctl->tp.work_cond),NULL);

    tpctl->tp.pool_destory = 0;
    tpctl->tp.thread_num = thread_num;
    tpctl->tp.worklist_size = 0;
    tpctl->tp.thread_id = (pthread_t *)malloc(thread_num * sizeof(pthread_t));
    tpctl->tp.worklist = NULL;

    uint32_t i;
    /*创建设定数目的子线程*/
    for (i = 0 ; i < thread_num ; i++) {
        pthread_create(&(tpctl->tp.thread_id[i]), NULL, thread_runing, tpctl);
    }
}

/*创建线程池并初始化*/
tpool_ctl_t *tpctl_create(uint32_t thread_num)
{
    tpool_ctl_t *tpctl = (tpool_ctl_t *)malloc(sizeof(tpool_ctl_t));
    if (NULL == tpctl) {
        return NULL;
    }
    tpctl_init(tpctl,thread_num);
    tpctl->add = tpool_addworker;
    tpctl->del = tpool_destory;
    return tpctl;
}

3,封装文件的使用。我们创建一个main.c文件,调用我们封装好的函数即可实现线程池操作了。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "sky_pool.h"

#define THREAD_NUM   3

void callback(void *arg) 
{
    printf("Be Yourself\n");
}

void callback1(void *arg) 
{
    sleep(1);
    printf("Peace&Love\n");
}

void callback2(void *arg) 
{
    printf("Keep Real\n");
    sleep(2);
}

int main()
{
    /*创建线程池*/
    tpool_ctl_t *tpctl = tpctl_create(THREAD_NUM);
    if (NULL == tpctl) {
        return 1;
    }
    while (1) {
        sleep(2);
        /*添加任务*/
        tpctl->add(tpctl,callback,NULL);
        tpctl->add(tpctl,callback1,NULL);
        tpctl->add(tpctl,callback2,NULL);
        sleep(5);
        break;
    }
    /*线程池销毁*/
    tpctl->del(tpctl);
    return 0;
}

4,总结:整体来说,线程池的通用简单实现还是不难的,我这边封装也是想多练练自己函数封装的能力,尽量做到简洁有效,让人一目了然。继续学习吧,保持一个封装的好习惯。

5,参考博文
一个Linux下C线程池的实现(转)

猜你喜欢

转载自blog.csdn.net/dancer__sky/article/details/78579441