线程池的使用

一、线程池的简介

线程池就是首先创建一些线程,它们的集合称为线程池。使用线程池可以很好地提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一条线程来执行这个任务,执行结束以后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。

二、为何引入线程池

传统多线程方案中我们采用的服务器模型则是一旦接受到请求之后,即创建一个新的线程,由该线程执行任务。任务执行完毕后,线程退出,这就“即时创建,即时销毁”的策略。尽管与创建进程相比,创建线程的时间已经大大的缩短,但是如果提交给线程的任务是执行时间较短,而且执行次数极其频繁,那么服务器将处于
不停的创建线程,销毁线程的状态,这笔开销将是不可忽略的。目前的大多数网络服务器,包括Web服务器、Email服务器以及数据库服务器等都具有一个共同点,就是单位时间内必须处理数目巨大的连接请求,但处理时间却相对较短。

三、线程池的特点

  • 经典生产者消费者模型
  • 线程池中有若干等待的线程
  • 线程池中的线程用于执行大量的相对短暂的任务
  • 在这里插入图片描述

四、线程池的工作流程

在这里插入图片描述

五、线程池对象

typedef struct{
pthread_mutex_t pool_lock; //互斥锁
pthread_cond_t cond; //条件变量
worker * queuehead; //队列头
int cur_queue_cont; //当前队列中成员个数
pthread_t * pthread_num; //线程号
int max_thread; //创建的线程的个数
int shutdown; //线程停止标志
}pool;
``
typedef struct work{
void * (*process)(void * arg); 
//执行任务的函数指针
void * args; //传递的参数
struct work * next; //指向队列的下一个成员
}worker;

六、线程条件变量

sudo apt-get install manpages-posix-dev
//安装man手册


int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); 
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 
**功能  :**初始化一个条件变量
**参数  :** @cond:条件变量
         @attr:NULL(linux 线程中忽略),所以直接填NULL**返回值 :**函数成功返回0;任何其他返回值都表示错误


int pthread_cond_destroy(pthread_cond_t *cond); 
**功能  :**销毁一个条件变量
**参数  :** @cond:条件变量
**返回值 :**函数成功返回0;任何其他返回值都表示错误

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
**功能**:wait on a condition 阻塞等待条件(让其阻塞休眠)
**参数**:@cond:条件变量
     @mutex:线程互斥锁
**返回值**:函数成功返回0;任何其他返回值都表示错误
**深入解析:**
1、阻塞等待条件满足后被唤醒;
2、如果条件不满足,释放互斥锁 pthread_mutex_unlock(&mutex);
3、当被唤醒时,解除阻塞,重新去申请互斥锁,phtread_mutex_lock(&mutex);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
**功能:**唤醒pthread_cond_wait阻塞的线程
**区别:**
	pthread_cond_signal:唤醒条件变量上的一个线程
	pthread_cond_broadcast:唤醒条件变量上所有的线程

七、线程池实例分析

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

typedef struct work{
 void * (*process)(void * arg);
 void * args;
 struct work * next;
}worker;
//线程池对象
typedef struct{
   pthread_mutex_t pool_lock;//互斥锁
   pthread_cond_t cond;//条件变量
   worker * queuehead;//队列头
   int cur_queue_cont;/当前队列中成员个数
   pthread_t * pthread_num;//线程号
   int max_thread;//创建的线程个数
   int shutdown;//线程停止标志
}pool;
//定义一个自己的线程池mypool,指针类型,在下面申请内存
pool *mypool;
void * thread_routine(void *args)//5个线程都是这个线程体,将线程号通过参数传递过来
{
     pthread_t *tid = (pthread_t *)args;//转换线程号,类型转换
     printf("start thread id = %ld.\n",*tid);
    while(1){  
       pthread_mutex_lock(&mypool->pool_lock);
       if(mypool->cur_queue_cont == 0 && !mypool->shutdown)
         {
             pthread_cond_wait(&mypool->cond,&mypool->pool_lock);//5个线程创建后不能执行,都在这里阻塞
         }
       if(mypool->shutdown)
         {
              pthread_mutex_unlock(&mypool->pool_lock);
              pthread_exit(NULL);
         }
    mypool->cur_queue_cont --;
    worker * work = mypool->queuehead;
    mypool->queuehead = work->next;
    pthread_mutex_unlock(&mypool->pool_lock);
    work->process((void *)work->args);
    }
}
void * invok_process(void * arg)
{
     sleep(2);
     printf("this is thread invok %d affair.\n",*(int *)arg);
}
void create_poll(int num)
{
    int i,ret;
    mypool = (pool *)malloc(sizeof(*mypool));//给mypool分配内存
    if(mypool == NULL)
    {
      printf("malloc pool memory is fail.\n");
       return ;
    }
  pthread_mutex_init(&mypool->pool_lock,NULL);//初始化互斥锁
  pthread_cond_init(&mypool->cond,NULL);//初始化条件变量
  mypool->queuehead = NULL;//将队列清空,因为创建线程池的时候还没有客户请求,队列里面没内容
  mypool->shutdown = 0;//表示线程的退出,当值为1的时候才表示退出,在创建的时候应置0
  mypool->max_thread = num;//线程最大个数
  mypool->pthread_num = (pthread_t *)malloc(num*sizeof(pthread_t));//分配存放5个线程号的内存
 for(i=0; i<num; i++)
{
  ret = pthread_create(&(mypool->pthread_num[i]),NULL,
  thread_routine,(void *)&(mypool->pthread_num[i]));
  if(ret != 0)
       {
         printf("create thread is fail.\n");
       }
    }
  }
void add_work(void * (*process)(void *),void *args)
{
 worker *work = (worker *)malloc(sizeof(worker));
 work->process = process;
 work->args = args;
 work->next = NULL;
 pthread_mutex_lock(&mypool->pool_lock);
 worker * pwork = mypool->queuehead;
if(pwork != NULL)
{
  while(pwork->next != NULL)
   pwork = pwork->next;
  pwork->next = work;
 }
 else
 {
  mypool->queuehead = work;
 }

  mypool->cur_queue_cont ++;
 pthread_mutex_unlock(&mypool->pool_lock);
 pthread_cond_signal(&mypool->cond);
}
void destory_pool()
{
     int i;
     mypool->shutdown = 1;
     pthread_cond_broadcast(&mypool->cond);
     for(i=0; i<mypool->max_thread; i++)
     {
         pthread_join(mypool->pthread_num[i],NULL);
     }
    free(mypool->pthread_num);
    worker * tmp;
   while(mypool->queuehead)
     {
      tmp = mypool->queuehead;
      mypool->queuehead = mypool->queuehead->next;
      free(tmp);
    }
    pthread_mutex_destroy(&mypool->pool_lock);
    pthread_cond_destroy(&mypool->cond);
}
int main(int argc, const char *argv[])
{
    int i,num[10];
    //create thread poll
    create_poll(5);//创建线程池内有五个线程
    sleep(2);
    //add work,模拟客户请求,客户请求是10个
   for(i=0; i<10; i++)
   {
	num[i] = i;
       add_work(invok_process,(void *)&num[i]);
   }
sleep(3);
 //destory
   destory_pool();
   free(mypool);
   printf("free resource is ok.\n");
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值