Linux C 线程池手写 项目(326行代码)

目录

知识点

一、痛点

二、解决

三、声明

创造线程池

毁灭线程池

往线程池增加任务

计算线程池中忙碌的线程数

计算线程池中存活的线程数

工作线程

管理线程

退出线程池

四、定义

任务

线程池

创建线程池

毁灭线程池

往线程池增加任务

计算线程池中忙碌的线程数

计算线程池中存活的线程数

工作线程

管理线程

线程退出

五、调试测试

六、结果展示

七、完整代码


知识点

多线程

线程复用性

加锁

信号量


一、痛点

执行完一个任务的线程,创建又销毁,面对多任务需要频繁的创建销毁线程,效率低下

二、解决

线程池,存放有多个线程,接收任务

由工作队列按序、按优先级接受任务,类似生产者

由工作线程读取队列中的任务,在线程池中执行,类似消费者

另有管理者线程,对任务数量远小于线程总数时,销毁一部分线程;对任务数量较多时,增加一部分线程

 

三、声明

创造线程池

ThreadPool *threadPoolCreate(int min, int max, int queueSize);

毁灭线程池

int threadPoolDestroy(ThreadPool* pool);

往线程池增加任务

void threadPoolAdd(ThreadPool* pool, void(*func)(void*), void* arg);

计算线程池中忙碌的线程数

int threadPoolBusyNum(ThreadPool* pool);

计算线程池中存活的线程数

int threadPoolAliveNum(ThreadPool* pool);

工作线程

void* worker(void* arg);

管理线程

void* manager(void* arg);

退出线程池

void threadExit(ThreadPool* pool);

四、定义

任务

typedef struct Task
{
    void (*function)(void* arg);
    void* arg;
}Task;

线程池

struct ThreadPool
{

    Task* taskQ;
    int queueCapacity;  // 容量
    int queueSize;      // 当前任务个数
    int queueFront;     // 队头 -> 取数据
    int queueRear;      // 队尾 -> 放数据

    pthread_t managerID;    // 管理者线程ID
    pthread_t *threadIDs;   // 工作的线程ID
    int minNum;             // 最小线程数量
    int maxNum;             // 最大线程数量
    int busyNum;            // 忙的线程的个数
    int liveNum;            // 存活的线程的个数
    int exitNum;            // 要销毁的线程个数
    pthread_mutex_t mutexPool;  // 锁整个的线程池
    pthread_mutex_t mutexBusy;  // 锁busyNum变量
    pthread_cond_t notFull;     // 任务队列是不是满了
    pthread_cond_t notEmpty;    // 任务队列是不是空了

    int shutdown;           // 是不是要销毁线程池, 销毁为1, 不销毁为0
};

创建线程池

ThreadPool* threadPoolCreate(int min, int max, int queueSize)
{
    ThreadPool* pool = (ThreadPool*)malloc(sizeof(ThreadPool));
    do 
    {
        if (pool == NULL)
        {
            printf("malloc threadpool fail...\n");
            break;
        }

        pool->threadIDs = (pthread_t*)malloc(sizeof(pthread_t) * max);
        if (pool->threadIDs == NULL)
        {
            printf("malloc threadIDs fail...\n");
            break;
        }
        memset(pool->threadIDs, 0, sizeof(pthread_t) * max);
        pool->minNum = min;
        pool->maxNum = max;
        pool->busyNum = 0;
        pool->liveNum = min;    // 和最小个数相等
        pool->exitNum = 0;
	
 if (pthread_mutex_init(&pool->mutexPool, NULL) != 0 ||
            pthread_mutex_init(&pool->mutexBusy, NULL) != 0 ||
            pthread_cond_init(&pool->notEmpty, NULL) != 0 ||
            pthread_cond_init(&pool->notFull, NULL) != 0)
        {
            printf("mutex or condition init fail...\n");
            break;
        }



pool->taskQ = (Task*)malloc(sizeof(Task) * queueSize);
        pool->queueCapacity = queueSize;
        pool->queueSize = 0;
        pool->queueFront = 0;
        pool->queueRear = 0;

        pool->shutdown = 0;

pthread_create(&pool->managerID, NULL, manager, pool);
        for (int i = 0; i < min; ++i)
        {
            pthread_create(&pool->threadIDs[i], NULL, worker, pool);
        }
        return pool;
    } while (0);

	if (pool && pool->threadIDs) free(pool->threadIDs);
    if (pool && pool->taskQ) free(pool->taskQ);
    if (pool) free(pool);

    return NULL;
}

毁灭线程池

int threadPoolDestroy(ThreadPool* pool)
{
    if (pool == NULL)
    {
        return -1;
    }
	pool->shutdown = 1;
	pthread_join(pool->managerID, NULL);
	for (int i = 0; i < pool->liveNum; ++i)
    {
        pthread_cond_signal(&pool->notEmpty);
    }
	if (pool->taskQ)
    {
        free(pool->taskQ);
    }
    if (pool->threadIDs)
    {
        free(pool->threadIDs);
    }

    pthread_mutex_destroy(&pool->mutexPool);
    pthread_mutex_destroy(&pool->mutexBusy);
    pthread_cond_destroy(&pool->notEmpty);
    pthread_cond_destroy(&pool->notFull);

    free(pool);
    pool = NULL;

    return 0;
}

往线程池增加任务

	void threadPoolAdd(ThreadPool* pool, void(*func)(void*), void* arg)
{
    pthread_mutex_lock(&pool->mutexPool);
    while (pool->queueSize == pool->queueCapacity && !pool->shutdown)
    {

	pthread_cond_wait(&pool->notFull, &pool->mutexPool);
    }
    if (pool->shutdown)
    {
        pthread_mutex_unlock(&pool->mutexPool);
        return;
    }
	pool->taskQ[pool->queueRear].function = func;
    pool->taskQ[pool->queueRear].arg = arg;
    pool->queueRear = (pool->queueRear + 1) % pool->queueCapacity;
    pool->queueSize++;

    pthread_cond_signal(&pool->notEmpty);
    pthread_mutex_unlock(&pool->mutexPool);
}

计算线程池中忙碌的线程数

int threadPoolBusyNum(ThreadPool* pool)
{
    pthread_mutex_lock(&pool->mutexBusy);
    int busyNum = pool->busyNum;
    pthread_mutex_unlock(&pool->mutexBusy);
    return busyNum;
}

计算线程池中存活的线程数

int threadPoolAliveNum(ThreadPool* pool)
{
    pthread_mutex_lock(&pool->mutexPool);
    int aliveNum = pool->liveNum;
    pthread_mutex_unlock(&pool->mutexPool);
    return aliveNum;
}

工作线程

void* worker(void* arg)
{
    ThreadPool* pool = (ThreadPool*)arg;

    while (1)
    {
        pthread_mutex_lock(&pool->mutexPool);
	while (pool->queueSize == 0 && !pool->shutdown)
        {
	pthread_cond_wait(&pool->notEmpty, &pool->mutexPool);
		if (pool->exitNum > 0)
            {
                pool->exitNum--;
                if (pool->liveNum > pool->minNum)
                {
                    pool->liveNum--;
                    pthread_mutex_unlock(&pool->mutexPool);
                    threadExit(pool);
                }
            }
        }
	 if (pool->shutdown)
        {
            pthread_mutex_unlock(&pool->mutexPool);
            threadExit(pool);
        }
	Task task;
        task.function = pool->taskQ[pool->queueFront].function;
        task.arg = pool->taskQ[pool->queueFront].arg;
	pool->queueFront = (pool->queueFront + 1) % pool->queueCapacity;
        pool->queueSize--;
	 pthread_cond_signal(&pool->notFull);
        pthread_mutex_unlock(&pool->mutexPool);

        printf("thread %ld start working...\n", pthread_self());
        pthread_mutex_lock(&pool->mutexBusy);
        pool->busyNum++;
        pthread_mutex_unlock(&pool->mutexBusy);
        task.function(task.arg);
        free(task.arg);
        task.arg = NULL;

        printf("thread %ld end working...\n", pthread_self());
        pthread_mutex_lock(&pool->mutexBusy);
        pool->busyNum--;
        pthread_mutex_unlock(&pool->mutexBusy);
    }
    return NULL;
}

管理线程

void* manager(void* arg)
{
    ThreadPool* pool = (ThreadPool*)arg;
    while (!pool->shutdown)
    {
	 sleep(3);
	 pthread_mutex_lock(&pool->mutexPool);
        int queueSize = pool->queueSize;
        int liveNum = pool->liveNum;
        pthread_mutex_unlock(&pool->mutexPool);
	 pthread_mutex_lock(&pool->mutexBusy);
        int busyNum = pool->busyNum;
        pthread_mutex_unlock(&pool->mutexBusy);
	 if (queueSize > liveNum && liveNum < pool->maxNum)
        {
            pthread_mutex_lock(&pool->mutexPool);
            int counter = 0;
            for (int i = 0; i < pool->maxNum && counter < NUMBER
                && pool->liveNum < pool->maxNum; ++i)
            {
                if (pool->threadIDs[i] == 0)
                {
                    pthread_create(&pool->threadIDs[i], NULL, worker, pool);
                    counter++;
                    pool->liveNum++;
                }
            }
            pthread_mutex_unlock(&pool->mutexPool);
        }
	 if (busyNum * 2 < liveNum && liveNum > pool->minNum)
        {
            pthread_mutex_lock(&pool->mutexPool);
            pool->exitNum = NUMBER;
            pthread_mutex_unlock(&pool->mutexPool);

		 for (int i = 0; i < NUMBER; ++i)
            {
                pthread_cond_signal(&pool->notEmpty);
            }
        }
    }
    return NULL;
}

线程退出

void threadExit(ThreadPool* pool)
{
    pthread_t tid = pthread_self();
    for (int i = 0; i < pool->maxNum; ++i)
    {
        if (pool->threadIDs[i] == tid)
        {
            pool->threadIDs[i] = 0;
            printf("threadExit() called, %ld exiting...\n", tid);
            break;
        }
    }
    pthread_exit(NULL);
}

五、调试测试

void taskFunc(void* arg)
{
    int num = *(int*)arg;
    printf("thread %ld is working, number = %d\n",
        pthread_self(), num);
    sleep(1);
}

int main()
{
	ThreadPool* pool = threadPoolCreate(3, 10, 100);
    for (int i = 0; i < 100; ++i)
    {
        int* num = (int*)malloc(sizeof(int));
        *num = i + 100;
        threadPoolAdd(pool, taskFunc, num);
    }

    sleep(30);

    threadPoolDestroy(pool);
    return 0;
}

六、结果展示

[joy1@192 a]$ ls
main.c  threadpool.c  threadpool.h
[joy1@192 a]$ gcc -std=c99 main.c threadpool.c -lpthread
[joy1@192 a]$ ls
a.out  main.c  threadpool.c  threadpool.h
[joy1@192 a]$ ./a.out 
thread 139973385463552 start working...
thread 139973385463552 is working, number = 100
thread 139973377070848 start working...
thread 139973377070848 is working, number = 101
thread 139973368678144 start working...
thread 139973368678144 is working, number = 102
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 103
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 104
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 105
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 106
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 107
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 108
thread 139973360285440 start working...
thread 139973360285440 is working, number = 109
thread 139973351892736 start working...
thread 139973351892736 is working, number = 110
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 111
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 112
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 113
thread 139973360285440 end working...
thread 139973360285440 start working...
thread 139973360285440 is working, number = 114
thread 139973351892736 end working...
thread 139973351892736 start working...
thread 139973351892736 is working, number = 115
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 116
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 117
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 118
thread 139973360285440 end working...
thread 139973360285440 start working...
thread 139973360285440 is working, number = 119
thread 139973351892736 end working...
thread 139973351892736 start working...
thread 139973351892736 is working, number = 120
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 121
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 122
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 123
thread 139973343500032 start working...
thread 139973343500032 is working, number = 124
thread 139973335107328 start working...
thread 139973335107328 is working, number = 125
thread 139973360285440 end working...
thread 139973360285440 start working...
thread 139973360285440 is working, number = 126
thread 139973351892736 end working...
thread 139973351892736 start working...
thread 139973351892736 is working, number = 127
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 128
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 129
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 130
thread 139973343500032 end working...
thread 139973343500032 start working...
thread 139973343500032 is working, number = 131
thread 139973335107328 end working...
thread 139973335107328 start working...
thread 139973335107328 is working, number = 132
thread 139973360285440 end working...
thread 139973360285440 start working...
thread 139973360285440 is working, number = 133
thread 139973351892736 end working...
thread 139973351892736 start working...
thread 139973351892736 is working, number = 134
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 135
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 136
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 137
thread 139973343500032 end working...
thread 139973343500032 start working...
thread 139973343500032 is working, number = 138
thread 139973335107328 end working...
thread 139973335107328 start working...
thread 139973335107328 is working, number = 139
thread 139973360285440 end working...
thread 139973360285440 start working...
thread 139973360285440 is working, number = 140
thread 139973351892736 end working...
thread 139973351892736 start working...
thread 139973351892736 is working, number = 141
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 142
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 143
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 144
thread 139973252609792 start working...
thread 139973252609792 is working, number = 145
thread 139973244217088 start working...
thread 139973244217088 is working, number = 146
thread 139973343500032 end working...
thread 139973343500032 start working...
thread 139973343500032 is working, number = 147
thread 139973335107328 end working...
thread 139973335107328 start working...
thread 139973335107328 is working, number = 148
thread 139973360285440 end working...
thread 139973360285440 start working...
thread 139973360285440 is working, number = 149
thread 139973351892736 end working...
thread 139973351892736 start working...
thread 139973351892736 is working, number = 150
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 151
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 152
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 153
thread 139973252609792 end working...
thread 139973252609792 start working...
thread 139973252609792 is working, number = 154
thread 139973244217088 end working...
thread 139973244217088 start working...
thread 139973244217088 is working, number = 155
thread 139973343500032 end working...
thread 139973343500032 start working...
thread 139973343500032 is working, number = 156
thread 139973335107328 end working...
thread 139973335107328 start working...
thread 139973335107328 is working, number = 157
thread 139973360285440 end working...
thread 139973360285440 start working...
thread 139973360285440 is working, number = 158
thread 139973351892736 end working...
thread 139973351892736 start working...
thread 139973351892736 is working, number = 159
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 160
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 161
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 162
thread 139973252609792 end working...
thread 139973252609792 start working...
thread 139973252609792 is working, number = 163
thread 139973244217088 end working...
thread 139973244217088 start working...
thread 139973244217088 is working, number = 164
thread 139973343500032 end working...
thread 139973343500032 start working...
thread 139973343500032 is working, number = 165
thread 139973335107328 end working...
thread 139973335107328 start working...
thread 139973335107328 is working, number = 166
thread 139973360285440 end working...
thread 139973360285440 start working...
thread 139973360285440 is working, number = 167
thread 139973351892736 end working...
thread 139973351892736 start working...
thread 139973351892736 is working, number = 168
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 169
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 170
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 171
thread 139973235824384 start working...
thread 139973235824384 is working, number = 172
thread 139973252609792 end working...
thread 139973252609792 start working...
thread 139973252609792 is working, number = 173
thread 139973244217088 end working...
thread 139973244217088 start working...
thread 139973244217088 is working, number = 174
thread 139973343500032 end working...
thread 139973343500032 start working...
thread 139973343500032 is working, number = 175
thread 139973335107328 end working...
thread 139973335107328 start working...
thread 139973335107328 is working, number = 176
thread 139973360285440 end working...
thread 139973360285440 start working...
thread 139973360285440 is working, number = 177
thread 139973351892736 end working...
thread 139973351892736 start working...
thread 139973351892736 is working, number = 178
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 179
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 180
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 181
thread 139973235824384 end working...
thread 139973235824384 start working...
thread 139973235824384 is working, number = 182
thread 139973252609792 end working...
thread 139973252609792 start working...
thread 139973252609792 is working, number = 183
thread 139973244217088 end working...
thread 139973244217088 start working...
thread 139973244217088 is working, number = 184
thread 139973343500032 end working...
thread 139973343500032 start working...
thread 139973343500032 is working, number = 185
thread 139973335107328 end working...
thread 139973335107328 start working...
thread 139973335107328 is working, number = 186
thread 139973360285440 end working...
thread 139973360285440 start working...
thread 139973360285440 is working, number = 187
thread 139973351892736 end working...
thread 139973351892736 start working...
thread 139973351892736 is working, number = 188
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 189
thread 139973377070848 end working...
thread 139973377070848 start working...
thread 139973377070848 is working, number = 190
thread 139973368678144 end working...
thread 139973368678144 start working...
thread 139973368678144 is working, number = 191
thread 139973235824384 end working...
thread 139973235824384 start working...
thread 139973235824384 is working, number = 192
thread 139973252609792 end working...
thread 139973252609792 start working...
thread 139973252609792 is working, number = 193
thread 139973244217088 end working...
thread 139973244217088 start working...
thread 139973244217088 is working, number = 194
thread 139973343500032 end working...
thread 139973343500032 start working...
thread 139973343500032 is working, number = 195
thread 139973335107328 end working...
thread 139973335107328 start working...
thread 139973335107328 is working, number = 196
thread 139973360285440 end working...
thread 139973360285440 start working...
thread 139973360285440 is working, number = 197
thread 139973351892736 end working...
thread 139973351892736 start working...
thread 139973351892736 is working, number = 198
thread 139973385463552 end working...
thread 139973385463552 start working...
thread 139973385463552 is working, number = 199
thread 139973377070848 end working...
thread 139973368678144 end working...
thread 139973235824384 end working...
thread 139973252609792 end working...
thread 139973244217088 end working...
thread 139973343500032 end working...
thread 139973335107328 end working...
thread 139973360285440 end working...
thread 139973351892736 end working...
thread 139973385463552 end working...
threadExit() called, 139973377070848 exiting...
threadExit() called, 139973368678144 exiting...
threadExit() called, 139973235824384 exiting...
threadExit() called, 139973252609792 exiting...
threadExit() called, 139973244217088 exiting...
threadExit() called, 139973343500032 exiting...
threadExit() called, 139973335107328 exiting...
threadExit() called, 139973351892736 exiting...
threadExit() called, 139973360285440 exiting...
[joy1@192 a]$ 
 

七、完整代码

threadpool.h

声明

#ifndef _THREADPOOL_H
#define _THREADPOOL_H

typedef struct ThreadPool ThreadPool;

ThreadPool *threadPoolCreate(int min, int max, int queueSize);

int threadPoolDestroy(ThreadPool* pool);

void threadPoolAdd(ThreadPool* pool, void(*func)(void*), void* arg);

int threadPoolBusyNum(ThreadPool* pool);

int threadPoolAliveNum(ThreadPool* pool);

void* worker(void* arg);

void* manager(void* arg);

void threadExit(ThreadPool* pool);
#endif  // _THREADPOOL_H

threadpool.c

定义

#include"threadpool.h"
#include<pthread.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>

const int NUMBER = 2;

typedef struct Task
{
    void (*function)(void* arg);
    void* arg;
}Task;

struct ThreadPool
{

    Task* taskQ;
    int queueCapacity;  // 容量
    int queueSize;      // 当前任务个数
    int queueFront;     // 队头 -> 取数据
    int queueRear;      // 队尾 -> 放数据

    pthread_t managerID;    // 管理者线程ID
    pthread_t *threadIDs;   // 工作的线程ID
    int minNum;             // 最小线程数量
    int maxNum;             // 最大线程数量
    int busyNum;            // 忙的线程的个数
    int liveNum;            // 存活的线程的个数
    int exitNum;            // 要销毁的线程个数
    pthread_mutex_t mutexPool;  // 锁整个的线程池
    pthread_mutex_t mutexBusy;  // 锁busyNum变量
    pthread_cond_t notFull;     // 任务队列是不是满了
    pthread_cond_t notEmpty;    // 任务队列是不是空了

    int shutdown;           // 是不是要销毁线程池, 销毁为1, 不销毁为0
};



ThreadPool* threadPoolCreate(int min, int max, int queueSize)
{
    ThreadPool* pool = (ThreadPool*)malloc(sizeof(ThreadPool));
    do 
    {
        if (pool == NULL)
        {
            printf("malloc threadpool fail...\n");
            break;
        }

        pool->threadIDs = (pthread_t*)malloc(sizeof(pthread_t) * max);
        if (pool->threadIDs == NULL)
        {
            printf("malloc threadIDs fail...\n");
            break;
        }
        memset(pool->threadIDs, 0, sizeof(pthread_t) * max);
        pool->minNum = min;
        pool->maxNum = max;
        pool->busyNum = 0;
        pool->liveNum = min;    // 和最小个数相等
        pool->exitNum = 0;
	
 if (pthread_mutex_init(&pool->mutexPool, NULL) != 0 ||
            pthread_mutex_init(&pool->mutexBusy, NULL) != 0 ||
            pthread_cond_init(&pool->notEmpty, NULL) != 0 ||
            pthread_cond_init(&pool->notFull, NULL) != 0)
        {
            printf("mutex or condition init fail...\n");
            break;
        }



pool->taskQ = (Task*)malloc(sizeof(Task) * queueSize);
        pool->queueCapacity = queueSize;
        pool->queueSize = 0;
        pool->queueFront = 0;
        pool->queueRear = 0;

        pool->shutdown = 0;

pthread_create(&pool->managerID, NULL, manager, pool);
        for (int i = 0; i < min; ++i)
        {
            pthread_create(&pool->threadIDs[i], NULL, worker, pool);
        }
        return pool;
    } while (0);

	if (pool && pool->threadIDs) free(pool->threadIDs);
    if (pool && pool->taskQ) free(pool->taskQ);
    if (pool) free(pool);

    return NULL;
}

int threadPoolDestroy(ThreadPool* pool)
{
    if (pool == NULL)
    {
        return -1;
    }
	pool->shutdown = 1;
	pthread_join(pool->managerID, NULL);
	for (int i = 0; i < pool->liveNum; ++i)
    {
        pthread_cond_signal(&pool->notEmpty);
    }
	if (pool->taskQ)
    {
        free(pool->taskQ);
    }
    if (pool->threadIDs)
    {
        free(pool->threadIDs);
    }

    pthread_mutex_destroy(&pool->mutexPool);
    pthread_mutex_destroy(&pool->mutexBusy);
    pthread_cond_destroy(&pool->notEmpty);
    pthread_cond_destroy(&pool->notFull);

    free(pool);
    pool = NULL;

    return 0;
}
	void threadPoolAdd(ThreadPool* pool, void(*func)(void*), void* arg)
{
    pthread_mutex_lock(&pool->mutexPool);
    while (pool->queueSize == pool->queueCapacity && !pool->shutdown)
    {

	pthread_cond_wait(&pool->notFull, &pool->mutexPool);
    }
    if (pool->shutdown)
    {
        pthread_mutex_unlock(&pool->mutexPool);
        return;
    }
	pool->taskQ[pool->queueRear].function = func;
    pool->taskQ[pool->queueRear].arg = arg;
    pool->queueRear = (pool->queueRear + 1) % pool->queueCapacity;
    pool->queueSize++;

    pthread_cond_signal(&pool->notEmpty);
    pthread_mutex_unlock(&pool->mutexPool);
}

int threadPoolBusyNum(ThreadPool* pool)
{
    pthread_mutex_lock(&pool->mutexBusy);
    int busyNum = pool->busyNum;
    pthread_mutex_unlock(&pool->mutexBusy);
    return busyNum;
}

int threadPoolAliveNum(ThreadPool* pool)
{
    pthread_mutex_lock(&pool->mutexPool);
    int aliveNum = pool->liveNum;
    pthread_mutex_unlock(&pool->mutexPool);
    return aliveNum;
}

void* worker(void* arg)
{
    ThreadPool* pool = (ThreadPool*)arg;

    while (1)
    {
        pthread_mutex_lock(&pool->mutexPool);
	while (pool->queueSize == 0 && !pool->shutdown)
        {
	pthread_cond_wait(&pool->notEmpty, &pool->mutexPool);
		if (pool->exitNum > 0)
            {
                pool->exitNum--;
                if (pool->liveNum > pool->minNum)
                {
                    pool->liveNum--;
                    pthread_mutex_unlock(&pool->mutexPool);
                    threadExit(pool);
                }
            }
        }
	 if (pool->shutdown)
        {
            pthread_mutex_unlock(&pool->mutexPool);
            threadExit(pool);
        }
	Task task;
        task.function = pool->taskQ[pool->queueFront].function;
        task.arg = pool->taskQ[pool->queueFront].arg;
	pool->queueFront = (pool->queueFront + 1) % pool->queueCapacity;
        pool->queueSize--;
	 pthread_cond_signal(&pool->notFull);
        pthread_mutex_unlock(&pool->mutexPool);

        printf("thread %ld start working...\n", pthread_self());
        pthread_mutex_lock(&pool->mutexBusy);
        pool->busyNum++;
        pthread_mutex_unlock(&pool->mutexBusy);
        task.function(task.arg);
        free(task.arg);
        task.arg = NULL;

        printf("thread %ld end working...\n", pthread_self());
        pthread_mutex_lock(&pool->mutexBusy);
        pool->busyNum--;
        pthread_mutex_unlock(&pool->mutexBusy);
    }
    return NULL;
}

void* manager(void* arg)
{
    ThreadPool* pool = (ThreadPool*)arg;
    while (!pool->shutdown)
    {
	 sleep(3);
	 pthread_mutex_lock(&pool->mutexPool);
        int queueSize = pool->queueSize;
        int liveNum = pool->liveNum;
        pthread_mutex_unlock(&pool->mutexPool);
	 pthread_mutex_lock(&pool->mutexBusy);
        int busyNum = pool->busyNum;
        pthread_mutex_unlock(&pool->mutexBusy);
	 if (queueSize > liveNum && liveNum < pool->maxNum)
        {
            pthread_mutex_lock(&pool->mutexPool);
            int counter = 0;
            for (int i = 0; i < pool->maxNum && counter < NUMBER
                && pool->liveNum < pool->maxNum; ++i)
            {
                if (pool->threadIDs[i] == 0)
                {
                    pthread_create(&pool->threadIDs[i], NULL, worker, pool);
                    counter++;
                    pool->liveNum++;
                }
            }
            pthread_mutex_unlock(&pool->mutexPool);
        }
	 if (busyNum * 2 < liveNum && liveNum > pool->minNum)
        {
            pthread_mutex_lock(&pool->mutexPool);
            pool->exitNum = NUMBER;
            pthread_mutex_unlock(&pool->mutexPool);

		 for (int i = 0; i < NUMBER; ++i)
            {
                pthread_cond_signal(&pool->notEmpty);
            }
        }
    }
    return NULL;
}

void threadExit(ThreadPool* pool)
{
    pthread_t tid = pthread_self();
    for (int i = 0; i < pool->maxNum; ++i)
    {
        if (pool->threadIDs[i] == tid)
        {
            pool->threadIDs[i] = 0;
            printf("threadExit() called, %ld exiting...\n", tid);
            break;
        }
    }
    pthread_exit(NULL);
}

main.c

测试

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

void taskFunc(void* arg)
{
    int num = *(int*)arg;
    printf("thread %ld is working, number = %d\n",
        pthread_self(), num);
    sleep(1);
}

int main()
{
	ThreadPool* pool = threadPoolCreate(3, 10, 100);
    for (int i = 0; i < 100; ++i)
    {
        int* num = (int*)malloc(sizeof(int));
        *num = i + 100;
        threadPoolAdd(pool, taskFunc, num);
    }

    sleep(30);

    threadPoolDestroy(pool);
    return 0;
}

shou

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值