一、线程池C语言实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <stdbool.h>
#include <assert.h>
#define MAX_THREAD_NUM 3
#define MAX_TASK_NUM 1000
#define DEBUG 0
#if DEBUG
#define LOG(...) printf(__VA_ARGS__)
#else
#define LOG(...)
#endif
#define LL_ADD(item, list) do{ \
item->ptrPrev = NULL; \
item->ptrNext = list; \
if(list != NULL) list->ptrPrev = item; \
list = item; \
}while(0)
#define LL_DEL(item, list) do{ \
if(item->ptrPrev != NULL) item->ptrPrev->ptrNext = item->ptrNext; \
if(item->ptrNext != NULL) item->ptrNext->ptrPrev = item->ptrPrev; \
if(item == list) list = item->ptrNext; \
item->ptrNext = NULL; \
item->ptrPrev = NULL; \
}while(0)
typedef struct tagThreadList{
pthread_t threadId;
struct ThreadPool *ptrPool;
bool isStop;
struct tagThreadList *ptrPrev;
struct tagThreadList *ptrNext;
}ThreadList;
typedef struct tagTaskList{
void (*ptrFunc)(struct tagTaskList *ptrTask, struct ThreadPool *ptrPool);
int userData;
struct tagTaskList *ptrPrev;
struct tagTaskList *ptrNext;
}TaskList;
typedef struct ThreadPool{
struct tagThreadList *ptrThreads;
struct tagTaskList *ptrTasks;
pthread_cond_t taskCond;
pthread_mutex_t taskMutex;
}ThreadPool;
static void *ThreadCallback(void *arg){
ThreadList *thread = (ThreadList *)arg;
LOG("create thread id:%ld\n", thread->threadId);
while(1){
pthread_mutex_lock(&thread->ptrPool->taskMutex);
while(thread->ptrPool->ptrTasks == NULL){
if(thread->isStop){
break;
}
pthread_cond_wait(&thread->ptrPool->taskCond, &thread->ptrPool->taskMutex);
}
if(thread->isStop){
pthread_mutex_unlock(&thread->ptrPool->taskMutex);
break;
}
TaskList *task = thread->ptrPool->ptrTasks;
LL_DEL(task, thread->ptrPool->ptrTasks);
pthread_mutex_unlock(&thread->ptrPool->taskMutex);
task->ptrFunc(task, thread->ptrPool);
LOG("id:%ld\t task->userData:%d\n", thread->threadId, task->userData);
}
LOG("The index of %ld thread exit\n", thread->threadId);
if(thread != NULL){
free(thread);
thread = NULL;
}
pthread_exit(NULL);
}
int ThreadPoolCreate(ThreadPool *ptrPool, int threadNum){
if(threadNum < 1) threadNum = 1;
if(ptrPool == NULL) return -1;
memset(ptrPool, 0, sizeof(ThreadPool));
pthread_cond_t blankCond = PTHREAD_COND_INITIALIZER;
memcpy(&ptrPool->taskCond, &blankCond, sizeof(pthread_cond_t));
pthread_mutex_t blankMutex = PTHREAD_MUTEX_INITIALIZER;
memcpy(&ptrPool->taskMutex, &blankMutex, sizeof(pthread_mutex_t));
for(int i = 0; i < threadNum; i++){
ThreadList *thread = (ThreadList *)malloc(sizeof(ThreadList));
if(thread == NULL){
perror("malloc");
return -2;
}
memset(thread, 0, sizeof(ThreadList));
thread->ptrPool = ptrPool;
int ret = pthread_create(&thread->threadId, NULL, ThreadCallback, thread);
if(ret < 0){
perror("pthread_create");
free(thread);
return -3;
}
LL_ADD(thread, ptrPool->ptrThreads);
}
LOG("ThreadPoolCreate succeed\n");
return 0;
}
void ThreadPoolDestroy(ThreadPool *ptrPool){
ThreadList *thread = NULL;
for(thread = ptrPool->ptrThreads; thread != NULL; thread = thread->ptrNext){
thread->isStop = true;
}
pthread_mutex_lock(&ptrPool->taskMutex);
pthread_cond_broadcast(&ptrPool->taskCond);
pthread_mutex_unlock(&ptrPool->taskMutex);
LOG("ThreadPoolDestroy succeed\n");
}
void ThreadPoolPush(ThreadPool *ptrPool, TaskList *task){
pthread_mutex_lock(&ptrPool->taskMutex);
LL_ADD(task, ptrPool->ptrTasks);
LOG("ThreadPoolPush:%d\n", task->userData);
pthread_cond_signal(&ptrPool->taskCond);
pthread_mutex_unlock(&ptrPool->taskMutex);
}
void Func(TaskList *task, ThreadPool *ptrPool){
static int handleNum = 0;
handleNum++;
printf("Processing task, task->userData:%d\n", task->userData);
if(handleNum == MAX_TASK_NUM){
LOG("The total processing task number is %d\n", handleNum);
ThreadPoolDestroy(ptrPool);
}
}
int main(){
ThreadPool ptrPool;
int ret = ThreadPoolCreate(&ptrPool, MAX_THREAD_NUM);
assert(ret == 0);
TaskList task[MAX_TASK_NUM];
for(int i = 0; i < MAX_TASK_NUM; i++){
task[i].ptrPrev = NULL;
task[i].ptrNext = NULL;
task[i].ptrFunc = Func;
task[i].userData = i;
ThreadPoolPush(&ptrPool, &task[i]);
}
int ind = 1;
while(1){
sleep(1);
printf("count:%d\n", ind++);
}
return 0;
}