线程池

来源:互联网 发布:2017淘宝多肉店铺推荐 编辑:程序博客网 时间:2024/06/05 23:47

1.线程池实现

(1)用于执行大量相对短暂的任务

(2)当任务增加的时候能够动态的增加线程中线程的数量值到达一个阈值

(3)当任务执行完毕的时候,能够动态的销毁线程池中的线程

(4)该线程池的实现本质也是生产者与消费者模型的应用。生产者线程向任务队列中添加任务,一旦队列有任务到来,如果有等待线程就唤醒来执行任务,如果没有等待线程且线程数没有达到阈值,就创建新线程来执行任务

2.代码

condition.h

//#pragma once#ifndef __INCLUDE_CONDITION_H__#define __INCLUDE_CONDITION_H__#include <pthread.h>#include <unistd.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_timewait(condition_t *cond,const struct timespec *abstime);int condition_signal(condition_t *cond);int condition_broadcast(condition_t *cond);//int condition_destory(condition_t *cond);#endif // __INCLUDE_CONDITION_H__

condition.cpp

#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){    pthread_cond_wait(&cond->pcond,&cond->pmutex);}int condition_timewait(condition_t *cond,const struct timespec * abstime){    return pthread_cond_timedwait(&cond->pcond,&cond->pmutex,abstime);}int condition_signal(condition_t *cond){    return pthread_cond_signal(&cond->pcond);}int condition_broadcast(condition_t *cond){    return pthread_cond_broadcast(&cond->pcond);}/*int condition_destory(condition_t *cond){    int status;    if((status = pthread_mutex_destory(&cond->pmutex)))    {        return status;    }    if((status = pthread_cond_destory(&cond->pcond)))    {        return status;    }    return 0;}*/
threadpool.h

#ifndef __ICNLUDE_THREADPOOL_H__#define __INCLUDE_THREADPOOL_H__#include "condition.h"//任务结构体,将任务放入队列由线程池中的线程来执行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;    //销毁线程池的时候置1    int quit;}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_destory(threadpool_t *pool);#endif // __INCLUDE_THREADPOOL_H__

threadpool.cpp

#include "threadpool.h"#include <stdlib.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <time.h>void *thread_routine(void *arg){//将子线程设置为分离状态,这样主线程可以不用joinpthread_detach(pthread_self());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);//等待2秒clock_gettime(CLOCK_REALTIME,&abstime);abstime.tv_sec += 2;int status = condition_timewait(&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--;if(pool->counter == 0) {condition_signal(&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){//生成新任务task_t *newtask = (task_t*)malloc(sizeof(task_t));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_signal(&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_destory(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_destory(&pool->ready);}

main.cpp

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include "threadpool.h"/* * 头文件包含次序 * C库,C++库,其他库.h,项目中.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);int i;for(i=0; i<10; i++) {int* arg = (int*)malloc(sizeof(int));*arg = i;threadpool_add_task(&pool, mytask, arg);}//sleep(15);threadpool_destory(&pool);return 0;}

Makefile

.PHONY:cleanCC=g++CFLAGS=-Wall -gALL=poolall:$(ALL)OBJS=threadpool.o main.o condition.o.c.o:$(CC) $(CFLAGS) -c $<pool:$(OBJS)$(CC) $(CFLAGS) $^ -o $@ -lpthread -lrtclean:rm -f $(ALL) *.o

执行结果: