一个简单的线程池实现
应用特点:
- 用于执行大量的相对短暂的任务
- 当任务增加的时候能够动态的增加线程池中线程的数量,直到达到一个阈值
- 当任务执行完毕的时候,能够动态的销毁线程池中的线程
- 线程池的实现本质上是生产者与消费者模型的应用. 生产者线程向任务队列中添加任务, 一旦队列中有任务到来, 如果有等待线程就唤醒来执行任务, 如果没有等待线程并且线程数没有达到阈值, 就创建新的线程来执行任务.
#ifndef _CONDITION_H_
#define _CONDITION_H_
#include <pthread.h>
typedef struct condition
{
pthread_mutex_t pmutex;
pthread_cond_t pcond;
} condition_t;
int condition_init(condition_t *cond);
int condition_lock(condition_t *cond);
int condition_unlock(condition_t *cond);
int condition_wait(condition_t *cond);
int condition_timedwait(condition_t *cond, const struct timespec *abstime);
int condition_sinal(condition_t *cond);
int condition_broadcast(condition_t *cond);
int condition_destroy(condition_t *cond);
#endif /*_CONDITION_H_*/
/* =================================================== */
#include "condition.h"
int condition_init(condition_t *cond)
{
int status;
if (status = pthread_mutex_init(&cond->pmutex, NULL))
return status;
if (status = pthread_cond_init(&cond->pcond, NULL))
return status;
return 0;
}
int condition_lock(condition_t *cond)
{
return pthread_mutex_lock(&cond->pmutex);
}
int condition_unlock(condition_t *cond)
{
return pthread_mutex_unlock(&cond->pmutex);
}
int condition_wait(condition_t *cond)
{
return pthread_cond_wait(&cond->pcond, &cond->pmutex);
}
int condition_timedwait(condition_t *cond, const struct timespec *abstime)
{
return pthread_cond_timedwait(&cond->pcond, &cond->pmutex, abstime)
}
int condition_sinal(condition_t *cond)
{
return pthread_cond_signal(&cond->pcond);
}
int condition_broadcast(condition_t *cond)
{
return pthread_cond_broadcast(&cond->pcond);
}
int condition_destroy(condition_t *cond)
{
int status;
if (status = pthread_mutex_destroy(&cond->pmutex))
return status;
if (status = pthread_cond_destroy(&cond->pcond))
return status;
return 0;
}
// 任务结构体, 将任务放入队列由线程池中的线程来执行
typedef struct task
{
void *(*run)(void *arg); //任务回调函数
void *arg; //回调函数参数
struct task *next;
} task_t;
// 线程池结构体
typedef struct threadpool
{
condition_t ready; // 任务准备就绪或线程池销毁通知
task_t * first; // 任务队列头指针
task_t * last; // 任务队列尾指针
int counter; // 线程池中当前线程数
int idle; // 线程池中当前正在等待任务的线程
int max_threads; // 线程池中最大允许的线程数
int quit; // 销毁线程池的时候置1
} threadpool_t;
// 初始化线程池
void threadpool_init(threadpool_t *pool, int threads);
// 往线程池中添加任务
void threadpool_add_task(threadpool_t *pool, void*(*run)(void *arg), void *arg);
// 销毁线程池
void threadpool_destroy(threadpool_t *pool);
//threadpool.c
#include "threadpool.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <time.h>
void *thread_routine(void *arg)
{
struct timespec abstime;
int timeout;
printf("thread 0x%x is starting\n",
(int)pthread_self());
threadpool_t *pool = (threadpool_t*)arg;
while (1)
{
timeout = 0;
condition_lock(&pool->ready);
// 刚创建好的线程肯定是空闲的
pool->idle++;
//等待任务队列,如果没有任务或线程池不通知销毁,则等待
while (pool->first == NULL && !pool->quit)
{
printf("thread 0x%x is waiting\n", (int)pthread_self());
//condition_wait(&pool->ready);
// 如果想让线程在空闲一定时间后自动销毁
clock_gettime(CLOCK_REALTIME, &abstime);
abstime.tv_sec += 2;
int status = condition_timedwait(&pool->ready, &abstime);
if (status == ETIMEDOUT)
{
printf("thread 0x%x is wait timed out\n", (int)pthread_self());
timeout = 1;
break;
}
}
// 有任务或销毁通知,不空闲了
pool->idle--;
// 如果有任务
if (pool->first != NULL)
{
// 从队列头取出任务
task_t *t = pool->first;
pool->first = t->next;
// 这里要解锁,并发时以便
// 生产者线程能够往队列中添加新任务
// 其它消费者线程能进入等待任务
condition_unlock(&pool->ready);
t->run(t->arg);
free(t);
// 这里再把锁加回去
condition_lock(&pool->ready);
}
// 如果等待到线程池销毁通知,且任务都执行完毕
if (pool->quit && pool->first == NULL)
{
pool->counter--;
// 当线程数量为0时,通知主线程销毁退出
if (pool->counter == 0)
{
condition_sinal(&pool->ready);
}
// 跳出循环前,记得要释放锁
condition_unlock(&pool->ready);
break;
}
// 如果超时
if (timeout && pool->first == NULL)
{
pool->counter--;
// 跳出循环前,记得要释放锁
condition_unlock(&pool->ready);
break;
}
condition_unlock(&pool->ready);
}
printf("thread 0x%x is exiting\n",
(int)pthread_self());
return NULL;
}
// 初始化线程池
void threadpool_init(threadpool_t *pool, int threads)
{
// 对线程池中的各个字 段初始化
condition_init(&pool->ready);
pool->first = NULL;
pool->last = NULL;
pool->counter = 0;
pool->idle = 0;
pool->max_threads = threads;
pool->quit = 0;
}
// 往线程池中添加任务
void threadpool_add_task(threadpool_t *pool, void*(*run)(void *arg), void *arg)
{
//void *(*run)(void *arg); //任务回调函数
//void *arg; //回调函数参数
struct task *next;
// 生成新任务
task_t *newtask = malloc(sizeof(task_t));
if (newtask)
{
newtask->run = run;
newtask->arg = arg;
newtask->next = NULL;
}
condition_lock(&pool->ready);
// 将任务添加到队列
if (pool->first == NULL)
pool->first = newtask;// 第一次添加
else
pool->last->next = newtask;
pool->last = newtask;
if (pool->idle > 0)
{
// 如果有等待线程,则唤醒其中一个
condition_sinal(&pool->ready);
}
else if (pool->counter < pool->max_threads)
{
// 如果没有等待线程,且当前线程数没有超过最大阈值
pthread_t tid;
pthread_create(&tid, NULL, thread_routine, pool);
pool->counter++;
}
condition_unlock(&pool->ready);
}
// 销毁线程池
void threadpool_destroy(threadpool_t *pool)
{
if (pool->quit)
{
return;
}
condition_lock(&pool->ready);
pool->quit = 1;
if (pool->counter > 0)
{
if (pool->idle > 0)
{
condition_broadcast(&pool->ready);
}
// 处于执行任务状态中的线程, 不会收到广播
// 线程池需要等待所有线程的任务执行完毕
while (pool->counter > 0)
{
condition_wait(&pool->ready);
}
}
condition_unlock(&pool->ready);
condition_destroy(&pool->ready);
}
/*============================================================*/
// 使用
#include "threadpool.h"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void* mytask(void *arg)
{
printf("thread 0x%x is working on task %d\n",
(int)pthread_self(), *(int*)arg);
sleep(1);
free(arg);
return NULL;
}
int main(void)
{
threadpool_t pool;
threadpool_init(&pool, 3); //3个线程的线程池
int i;
for (i = 0; i < 10; ++i)
{
int *arg = (int*)malloc(sizeof(i));
*arg = i;
threadpool_add_task(&pool, mytask, arg);
}
//sleep(15);
threadpool_destroy(&pool);
return 0;
}