文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

线程池的使用场景和代码实现!

2024-12-03 03:56

关注

好了简单说了一下,后面的哪些什么内存池、连接池,后期复习都再给大家分享吧,今天我们的主题是线程池。

一、线程池的实现:

1、为啥要用到线程池?

多线程编程,大家这个应该很熟悉了,上次有一位朋友问了一个问题,一个线程大概占用多大内存大小,一般按照POSIX标准来算的话,一个线程大概在8M左右,但是我们一般内存资源有限,在进行高并发的时候,比如说,多个客户端同时向服务器端发送请求:

这个时候,你想一下给这么多客户端都分配开一个大概8M的内存大小,这现实嘛,显然行不通的嘛,我们来计算一下:

所以百万级个客户端都分配开一个线程的话,那内存资源肯定是不够的,所以这涉及到我们的线程池了,这也是为什么在这种场景下要使用线程池了!

为了帮助大家更好的理解线程池这个概念,我们还是举一个生活当中的实际场景吧;去银行存钱或者办理相关业务,这个大家都不陌生吧,你到了银行里面,一般来说的话,都要排队在窗口等待前面的人把业务办理完,才能够轮到你来办理你想要办理的业务,而窗口里面就是帮你办理各种业务的银行工作人员,同时一般窗口办理业务上面有一个提示电子信息,如果轮到了你,就会通知你,你就知道了轮到自己办理业务了。

这里换个专业的角度来说(也不专业哈,只是一个打比方),你来办理的这个业务就是一个任务(也就是一个线程,可以说成任务队列,因为要排队嘛,不可能一下子执行那么多任务,任务队列里面的任务必须一个一个执行),而银行工作人员相当于从任务队列里面拿一个任务来执行,你可以把银行工作人员看成是执行任务队列;而电子显示通知信息,你可以把它看成防止多个业务同时在一个窗口让一个银行工作人员来办理,两个窗口也就是两个银行工作人员同时办理一个业务,也就是说这个电子显示信息是一个管理组件,管理任务是否可以去办理,管理着银行工作人员是否开始办理业务任务,不让他们乱套了,合理有效的执行任务。

那么你从上面可以看到,使用线程池的优点了:

2、线程池实现模板步骤:

其实这个线程池的实现大概流程步骤都差不多,如果大家平时仔细看公司代码或者说自己去实现一个线程池的话,大概实现模板如下:

3、线程池实现结构体定义:

任务队列:

  1. struct nTask 
  2. //用函数指针来存放不同的任务 
  3.   void (*task_func)(struct nTask *task); 
  4.    
  5.   //这个参数用来做任务执行的参数 
  6.   void *user_data; 
  7.  
  8. //链表节点的定义,这里采用链表的方式实现 
  9. struct nTask *prev; 
  10. struct nTask *next
  11.  
  12. }; 
  1. struct nWorker 
  2.   pthread_t threadid;//线程id 
  3.    
  4.   int terminate;//表示是否终止任务 
  5.  //表示银行工作人员要执行任务还要向执行组件通告一下 
  6.   struct nManager *manager; 
  7.    
  8.   //还是通过链表的方式来实现执行队列 
  9.   struct nWorker *prev; 
  10.   struct nWorker *next
  11.  
  12. }; 

注意:这里如果没有办理业务的人来,银行工作人员只能在哪里等待任务的到来,然后再执行任务。

  1. typedef struct nManager 
  2.  
  3.   struct nTask *task; 
  4.   struct nWorker *workers; 
  5.    
  6.   pthread_mutex_t mutex;//互斥锁 
  7.   pthread_cond_t cond;//条件变量 
  8. }ThreadPool; 
  1. //插入 
  2. #define LIST_INSERT(item,list) do{\ 
  3.   item->prev=NULL;                \ 
  4.   item->next=list;                \ 
  5. if((list)!=NULL) list->prev=item;\ 
  6. list=item; 
  7. }while(0) 
  8.  
  9. //删除 
  10. #define LIST_REMOVE(item,list) do{ \ 
  11. if(item->prev != NULL) item->prev->next = item->next; \ 
  12. if(item->next !=NULL) item->next->prev=item->prev;  \ 
  13.  
  14. if(list == item)list = item->netx; \  
  15. item->prev=item->next=NULL;\ 
  16. }while(0) 
  17.  

4、线程池接口定义如下:

1、线程池初始化接口:

  1. int nThreadPoolCreate(ThreadPool *pool,int numWorkers) 
  2. //参数pool表示线程池,numWorkers表示线程池里面有多少个任务 

2、线程池销毁接口:

  1. int nThreadPoolDestory(ThreadPool *pool,int nWorker) 
  2.  

3、往线程池里面添加任务接口:

  1. int nThreadPoolPushTask(ThreadPool *pool,struct nTask *task) 
  2.  
  3.  

4、线程回调函数:

  1. void *nThreadPoolCallback(void *arg) 
  2.  
  3.  

二、线程池工程代码:

  1. #include  
  2. #include  
  3. #include  
  4. #include  
  5.  
  6. //链表插入 
  7. #define LIST_INSTER(item,list)do{ \ 
  8. item->prev=NULL;       \ 
  9. item->next=next;       \ 
  10. if(list!=NULL) list->prev=item; \ 
  11. list=item; 
  12. }while(0) 
  13.  
  14. //删除 
  15. #define LIST_REMOVE(item,list)do {  \ 
  16. if(item->prev!=NULL)item->prev->next=item->next; \ 
  17. if(item->next!=NULL)itme->next->prev=item->prev;\ 
  18.  
  19. if(list==item)list=item->next
  20. item->prev=item->next=NULL
  21. }while(0) 
  22.  
  23. //任务队列 
  24.  
  25. struct nTask 
  26.   void(*task_funt)(struct nTask *task); 
  27.   void *uset_data; 
  28.    
  29.   struct nTask *prev; 
  30.   struct nTask *next
  31. }; 
  32.  
  33. //执行队列 
  34. struct nWorker 
  35.   pthread_t threadid; 
  36.   int terminate; 
  37.    
  38.   struct nManager *manager; 
  39.    
  40.   struct nWorker *prev; 
  41.   struct nWorker *next
  42. }; 
  43.  
  44. //管理组件 
  45. typedef struct nManager 
  46.   struct nTask *tasks; 
  47.   struct nWoker *workers; 
  48.    
  49.   pthread_mutex_t mutex; 
  50.   pthread_cond_t cond; 
  51.  
  52. }ThreadPool; 
  53. //线程回调函数 
  54. void *nThreadPoolCallback(void *arg) 
  55.   struct nWorker *worker=(struct nWorker*)arg; 
  56.    
  57.   while(1) 
  58.   { 
  59.     //判断是否有任务 
  60.     pthread_mutex_lock(&worker->manager-mutex); 
  61.     while(worker->manager->tasks==NULL
  62.     { 
  63.       if(worker-terminate) 
  64.         break; 
  65.       pthread_cond_wait(&worker->manager->cond,&worker->manager->mutex);//如果没有任务,一直等待任务的到来 
  66.     } 
  67.     if(worker->terminate) 
  68.     { 
  69.       pthread_mutex_unlock(&worker->manager->mutex); 
  70.       break; 
  71.      
  72.     } 
  73.   struct nTask *task = worker->manager->tasks; 
  74.   LIST_REMOVE(task,worker->manager->tasks); 
  75.   pthread_mutex_unlock(&worker->manager->mutex); 
  76.   task->task_func(task); 
  77.    
  78.   } 
  79.  
  80. free(worker); 
  81.  
  82. //创建线程池 
  83. int nThreadPoolCreate(ThreadPool *pool, int numWorkers) 
  84.   if(pool == NULLreturn -1; 
  85.   if(numWorkers < 1)numWorkers =1; 
  86.   memset(&pool,0,sizeof(ThreadPool)); 
  87.  
  88.   //开始初始化 
  89.   pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER; 
  90.  
  91.   memcpy(&pool->cond,&blank_cond,sizeof(pthread_cond_t)); 
  92.  
  93.   pthread_mutex_t blank_mutex =PTHREAD_MUTEX_INITIALIZER; 
  94.   memcpy(&pool->mutex,&blank_mutex,sizeof(pthread_mutex_t)); 
  95.  
  96.   int i =0;//开线程的个数,也就是执行任务的个数 
  97.  
  98.   for(i=0;i < numWorkers;i++) 
  99.   { 
  100.     struct nWorker *worker =(struct nWorker*)malloc(sizeof(struct nWorker)); 
  101.     if(worker == NUll
  102.     { 
  103.         perror("malloc"); 
  104.         return -2; 
  105.     } 
  106.     memset(worker,0,sizeof(struct nWorker)); 
  107.     worker->manager=pool; 
  108.  
  109.   //创建线程 
  110.   int ret=pthread_create(&worker->pthreadid,NULL,nThreadPoolCallback,worker); 
  111.    
  112.     if(ret) 
  113.     { 
  114.       perror("pthread_create"); 
  115.       free(worker); 
  116.       return -3; 
  117.     } 
  118.     LIST_INSERT(worker,pool->workers); 
  119.   } 
  120.  
  121. //线程池销毁 
  122.  
  123. int nThreadPoolDestory(ThreadPool *pool,int nWorker) 
  124.   struct nWorker *worker = NULL
  125.   for(worker=pool->workers;worker!=NULL;worker=worker->next
  126.   { 
  127.     worker->terminate; 
  128.   } 
  129. pthread_mutex_lock(&pool->mutex); 
  130. pthread_cond_broadcast(&pool->cond);//做一个广播通知 
  131. pthread_mutex_unlock(&pool->mutex); 
  132.  
  133. pool->workers = NULL
  134. pool->tasks = NULL
  135.  
  136. //往线程池里面添加任务 
  137.  
  138. int nThreadPoolPushTask(ThreadPool *pool,struct nTask *task) 
  139.   pthread_mutex_lock(&pool->mutex); 
  140.   LIST_INSERTER(task,pool->tasks); 
  141.   pthread_cond_sigal(&pool->cond);// 发送一个信号,有人来办理业务了 
  142.   pthread_mutex_unlock(&pool-mutex); 
  143.  
  144.  
  145. #if 1 
  146.  
  147. #define THREADPOOL_INIT_COUNT 20 
  148. #define TASK_INIT_SIZE   1000 
  149.  
  150.  
  151. void task_entry(struct nTask *task) { //type  
  152.  
  153.  //struct nTask *task = (struct nTask*)task; 
  154.  int idx = *(int *)task->user_data; 
  155.  
  156.  printf("idx: %d\n", idx); 
  157.  
  158.  free(task->user_data); 
  159.  free(task); 
  160.  
  161.  
  162. int main(void) { 
  163.  
  164.  ThreadPool pool = {0}; 
  165.   
  166.  nThreadPoolCreate(&pool, THREADPOOL_INIT_COUNT); 
  167.  // pool --> memset(); 
  168.   
  169.  int i = 0; 
  170.  for (i = 0;i < TASK_INIT_SIZE;i ++) { 
  171.   struct nTask *task = (struct nTask *)malloc(sizeof(struct nTask)); 
  172.   if (task == NULL) { 
  173.    perror("malloc"); 
  174.    exit(1); 
  175.   } 
  176.   memset(task, 0, sizeof(struct nTask)); 
  177.  
  178.   task->task_func = task_entry; 
  179.   task->user_data = malloc(sizeof(int)); 
  180.   *(int*)task->user_data  = i; 
  181.  
  182.    
  183.   nThreadPoolPushTask(&pool, task); 
  184.  } 
  185.  
  186.  getchar(); 
  187.   

代码量稍微有点多,大家可以多多看看几遍!

本文转载自微信公众号「txp玩Linux」,可以通过以下二维码关注。转载本文请联系txp玩Linux公众号。

 

来源:txp玩Linux内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯