线程池实现

线程池原理与实现
本文深入探讨了线程池的工作原理,详细介绍了如何在C语言中实现一个基本的线程池,包括线程的创建、任务的分配与执行、线程池的初始化与退出过程。同时,提供了完整的代码示例和测试用例,帮助读者理解线程池的内部机制。

由于工作需要实现一个线程池,所以这里做一个小总结并分享给大家,如有问题请大家不吝指教。

  1. 线程池(thread pool)是线程的一种使用模式。因为,过多的线程调度开销会影响缓存局部性和系统整体性能。所以,通过线程池维护着多个线程,等待着监督管理者分配可并发执行的任务,这就避免了在处理短时间任务时创建与销毁线程的代价。 线程池不仅能够保证内核的充分利用,还能防止过分调度。
  2. 可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。例如,线程数一般取cpu数量+2比较合适,线程数过多会导致额外的线程切换开销。
    完整代码下载地址:线程池代码下载链接
    thrpool.c文件。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>

#include "thrPool.h"

static void *thread_start(struct thrPool *pool) {
    for (;;) {
        printf("Wait cond Current thread id: %d\n", (unsigned int)pthread_self());

        pthread_mutex_lock(&pool->mutex);
        while (pool->jobSize == 0 && !pool->destroyFlag) {
            pthread_cond_wait(&pool->cond, &pool->mutex);
            //printf("get new job: thread id: %d\n", (unsigned int)pthread_self());
        }
        if (pool->destroyFlag) {
            pthread_mutex_unlock(&pool->mutex);
            //printf("thread %d will exit.\n", (unsigned int )pthread_self());
            pthread_exit(NULL);
        }

		// 获取任务并执行
    
    }

    // never executed
    pthread_exit(NULL);
    return NULL;
}

int thrPoolInit(struct thrPool **pool, unsigned int number)
{
    int val = -1;

    if ((number < 1) && (number > THR_MAX_NUM) && (pool == NULL)) {
        printf("Invalid Params.\n");
        val = RET_INVALID_PARAMS;
        goto _err_out_params;
    }

    struct thrPool *tmp = malloc(sizeof(struct thrPool));
    if (tmp == NULL) {
        printf("Alloc Mem Fail.\n");
        val = RET_NO_MEMORY;
        goto _err_out_pool_mem;
    }

    val = pthread_mutex_init(&tmp->mutex, NULL);
    if (val < 0) {
        printf("Mutex Init Fail.\n");
        val = RET_ERROR;
        goto _err_out_mutex_init;
    }

    val = pthread_cond_init(&tmp->cond, NULL);
    if (val < 0) {
        printf("Cond Init Fail.\n");
        val = RET_ERROR;
        goto _err_out_cond_init;
    }

    val = thrJobInit(&tmp->jobRoot);
    if (val < 0) {
        printf("Init Job List Fail.\n");
        val = RET_ERROR;
        goto _err_out_job_init;
    }

    int i = 0;
    for (i = 0; i < number; i++) {
        val = pthread_create(&tmp->threadId[i], NULL, (void *)&thread_start, tmp);
        if (val != 0) {
            printf("Create Thread Fail.\n");
            val = RET_ERROR;
            goto _err_out_thread_create;
        }
    }

    if (i != number) {
        goto _err_out_thread_create2;
    }

    tmp->destroyFlag = 0;
    tmp->thrNum = number;
    *pool = tmp;

    return RET_OK;

_err_out_thread_create2:
    // wakeup all thread
    pthread_cond_broadcast(&tmp->cond);
    for (int k = 0; k < number; k++) {
        if (tmp->threadId[k] != 0)
            pthread_join(tmp->threadId[k], NULL);     //block
    };
_err_out_thread_create:
    thrJobDestroy(tmp->jobRoot);
_err_out_job_init:
    pthread_cond_destroy(&tmp->cond);
_err_out_cond_init:
    pthread_mutex_destroy(&tmp->mutex);
_err_out_mutex_init:
    free(tmp);
_err_out_pool_mem:
_err_out_params:

    return val;
}

int thrPoolWorkerAdd(struct thrPool *pool, subThrFunc func, void *args)
{
    int val = -1;

    if ((pool == NULL) && (func == NULL) && (args == NULL)) {
        return RET_INVALID_PARAMS;
    }

    struct thrJobNode *newJobNode = (struct thrJobNode *)malloc(sizeof( struct thrJobNode ));
    if (newJobNode == NULL) {
        printf("Alloc Mem Fail.\n");
        val = RET_NO_MEMORY;
        goto _err_out_new_job;
    }
    newJobNode->procFunction = func;
    newJobNode->args = args;
    newJobNode->next = NULL;

    // add new job to list(tail);
    pthread_mutex_lock(&pool->mutex);
    struct thrJobNode *node = pool->jobRoot;
    assert(node != NULL);
    while(node->next != NULL) {
        node = node->next;
    }
    node->next = newJobNode;
    pool->jobSize++;
    pthread_mutex_unlock(&pool->mutex);

    // wakeup one thread, if all thread busy,
    pthread_cond_signal(&pool->cond);

    //printf("Add New Job Ok.\n");
    return RET_OK;

_err_out_new_job:
    return val;
}

int thrPoolExit(struct thrPool *pool)
{
    int val = -1;

    if (pool == NULL) {
        printf("Invalid Params.\n");
        val = RET_INVALID_PARAMS;
        goto _err_out_params;
    }

    if (pool->destroyFlag) {
        return RET_OK;
    }

    printf("size:%d\n", pool->jobSize);
    pool->destroyFlag = 1;
    pthread_cond_broadcast(&pool->cond);
    for (int i = 0; i < pool->thrNum; i++) {
        val = pthread_join(pool->threadId[i], NULL);
    }
    printf("Join Thraed ok.\n");

    struct thrJobNode *head = pool->jobRoot;
    assert(head != NULL);
    while (head->next != NULL) {
        struct thrJobNode *tmp = head->next;
        head->next = tmp->next;
        tmp->next = NULL;
        free(tmp);
        tmp = NULL;
    }

    thrJobDestroy(pool->jobRoot);
    pthread_mutex_destroy(&pool->mutex);
    pthread_cond_destroy(&pool->cond);

    free(pool);
    pool = NULL;

    return RET_OK;

_err_out_params:
    return val;
}

测试用例main.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

#include "thrPool.h"

struct testDataInfo {
    int a;
};

static void testFunc(void *args)
{
    struct testDataInfo *data = (struct testDataInfo *)args;
    //sleep(data->a);
    printf("\n=====================\nthread id:%d data: %d\n", (unsigned int)pthread_self(), data->a);

    return;
}

int main (void)
{
    int val = -1;
    int thrNum = 5;
    struct thrPool *pool = NULL;
    struct testDataInfo *data = malloc(sizeof( struct testDataInfo ));
    struct testDataInfo *data1 = malloc(sizeof( struct testDataInfo ));
    struct testDataInfo *data2 = malloc(sizeof( struct testDataInfo ));

    val = thrPoolInit(&pool, thrNum);
    if (val != 0) {
        printf("Init Pool Fail.\n");
        goto _err_out_init;
    }

    while(1) {
        data->a = 3;
        thrPoolWorkerAdd(pool, (void *)&testFunc, data);

        data1->a = 1;
        thrPoolWorkerAdd(pool, (void *)&testFunc, data1);

        data2->a = 5;
        thrPoolWorkerAdd(pool, (void *)&testFunc, data2);

        sleep(2);
    }

    val = thrPoolExit(pool);
    while(1) {
        sleep(100);
    }
	return 0;
	
_err_out_init:
    exit(1);
}

测试结果:

 ./a.out 
Wait cond Current thread id: -662223104
Wait cond Current thread id: -679008512
Wait cond Current thread id: -670615808
Wait cond Current thread id: -805308672
Wait cond Current thread id: -687401216

=====================
thread id:-662223104 data: 3
Wait cond Current thread id: -662223104

=====================
thread id:-670615808 data: 1
Wait cond Current thread id: -670615808

=====================
thread id:-679008512 data: 5
Wait cond Current thread id: -679008512

=====================
thread id:-805308672 data: 3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值