溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Linux C下線程池有什么用

發(fā)布時間:2021-10-28 14:04:03 來源:億速云 閱讀:123 作者:小新 欄目:系統(tǒng)運維

這篇文章主要介紹了Linux C下線程池有什么用,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

線程池也是多線程的處理方式。是將“生產(chǎn)者”線程提出任務(wù)添加到“任務(wù)隊列”,然后一些線程自動完成“任務(wù)隊列”上的任務(wù)。

多線程編程,創(chuàng)建一個線程,指定去完成某一個任務(wù),等待線程的退出。雖然能夠滿足編程需求,但是當(dāng)我們需要創(chuàng)建大量的線程的時候,在創(chuàng)建過程以及銷毀線程的過程中可能會消耗大量的CPU.增加很大開銷。如:文件夾的copy、WEB服務(wù)器的響應(yīng)。

線程池就是用來解決類似于這樣的一個問題的,可以降低頻繁地創(chuàng)建和銷毀線程所帶來地開銷。

線程池技術(shù)思路:一般采用預(yù)創(chuàng)建線程技術(shù),也就是提前把需要用線程先創(chuàng)建一定數(shù)目。這些線程提前創(chuàng)建好了之后,“任務(wù)隊列”里面假設(shè)沒有任務(wù),那么就讓這些線程休眠,一旦有任務(wù),就喚醒線程去執(zhí)行任務(wù),任務(wù)執(zhí)行完了,也不需要去銷毀線程,直到當(dāng)你想退出或者是關(guān)機時,這個時候,那么你調(diào)用銷毀線程池地函數(shù)去銷毀線程。

線程完成任務(wù)之后不會銷毀,而是自動地執(zhí)行下一個任務(wù)。而且,當(dāng)任務(wù)有很多,你可以有函數(shù)接口去增加線程數(shù)量,當(dāng)任務(wù)較少時,你可以有函數(shù)接口去銷毀部分線程。

如果,創(chuàng)建和銷毀線程的時間對比執(zhí)行任務(wù)的時間可以忽略不計,那么我們在這種情況下面也就沒有必要用線程池。

“任務(wù)隊列”是一個共享資源“互斥訪問”

Linux C下線程池有什么用

線程池本質(zhì)上也是一個數(shù)據(jù)結(jié)構(gòu),需要一個結(jié)構(gòu)體去描述它:

struct pthread_pool //線程池的實現(xiàn) {  //一般會有如下成員   //互斥鎖,用來保護這個“任務(wù)隊列”  pthread_mutex_t lock; //互斥鎖     //線程條件變量 表示“任務(wù)隊列”是否有任務(wù)  pthread_cond_t cond; //條件變量    bool shutdown; //表示是否退出程序 bool:類型 false / true   //任務(wù)隊列(鏈表),指向第一個需要指向的任務(wù)  //所有的線程都從任務(wù)鏈表中獲取任務(wù) "共享資源"  struct task * task_list;    //線程池中有多個線程,每一個線程都有tid, 需要一個數(shù)組去保存tid  pthread_t * tids; //malloc()     //線程池中正在服役的線程數(shù),當(dāng)前線程個數(shù)  unsigned int active_threads;    //線程池任務(wù)隊列最大的任務(wù)數(shù)量  unsigned int max_waiting_tasks;    //線程池任務(wù)隊列上當(dāng)前有多少個任務(wù)  unsigned int cur_waiting_tasks;    //......  };  //任務(wù)隊列(鏈表)上面的任務(wù)結(jié)點,只要能夠描述好一個任務(wù)就可以了, //線程會不斷地任務(wù)隊列取任務(wù) struct task  //任務(wù)結(jié)點  {  // 1. 任務(wù)結(jié)點表示的任務(wù),“函數(shù)指針”指向任務(wù)要執(zhí)行的函數(shù)(cp_file)  void*(* do_task)(void * arg);    //2. 指針,指向任務(wù)指向函數(shù)的參數(shù)(文件描述符)  void * arg;    //3. 任務(wù)結(jié)點類型的指針,指向下一個任務(wù)  struct task * next; };

線程池框架代碼如下,功能自填:

操作線程池所需要的函數(shù)接口:pthread_pool.c 、pthread_pool.h

把“線程池”想象成一個外包公司,你需要去完成的就是操作線程池所提供的函數(shù)接口。

pthread_pool.c

#include "pthread_pool.h"  /*  init_pool: 線程池初始化函數(shù),初始化指定的線程池中有thread_num個初始線程  @pool:指針,指向您要初始化的那個線程池  @threa_num: 您要初始化的線程池中開始的線程數(shù)量  返回值:    成功 0   失敗 -1 */  int init_pool(pthread_pool * pool , unsigned int threa_num) {  //初始化線程池的結(jié)構(gòu)體    //初始化線程互斥鎖  pthread_mutex_init(&pool->lock, NULL);    //初始化線程條件變量  pthread_cond_init(&pool->cond, NULL);   pool->shutdown = false ;// 不退出   pool->task_list = (struct task*)malloc(sizeof(struct task));   pool->tids = (pthread_t *)malloc(sizeof(pthread_t) * MAX_ACTIVE_THREADS);  if(pool->task_list == NULL || pool->tids == NULL)  {   perror("malloc memery error");   return -1;  }   pool->task_list->next = NULL;   //線程池中一開始初始化多少個線程來服役  pool->active_threads = threa_num;   //表示線程池中最多有多少個任務(wù)  pool->max_waiting_tasks = MAX_WAITING_TASKS;   //線程池中任務(wù)隊列當(dāng)前的任務(wù)數(shù)量  pool->cur_waiting_tasks = 0;   //創(chuàng)建thread_num個線程,并且讓線程去執(zhí)行任務(wù)調(diào)配函數(shù),  //記錄所有線程的tid  int i = 0;  for(i = 0; i < threa_num; i++)  {   int ret = pthread_create(&(pool->tids)[i], NULL, routine, (void*)pool);   if(ret != 0)   {    perror("create thread error");    return -1;   }    printf("[%lu]:[%s] ===> tids[%d]:[%lu]",pthread_self(),    __FUNCTION__, i , pool->tids[i]);  }   return 0; }  /*  routine: 任務(wù)調(diào)配函數(shù)。   所有線程開始都執(zhí)行此函數(shù),此函數(shù)會不斷的從線程池的任務(wù)隊列   中取下任務(wù)結(jié)點,去執(zhí)行。      任務(wù)結(jié)點中包含“函數(shù)指針” h "函數(shù)參數(shù)" */  void * routine(void * arg) {  //arg表示你的線程池的指針    while()  {   //獲取線程互斥鎖,lock       //當(dāng)線程池沒有結(jié)束的時候,不斷地從線程池的任務(wù)隊列取下結(jié)點   //去執(zhí)行。      //釋放線程互斥鎖,unlock      //釋放任務(wù)結(jié)點  } }  /*  destroy_pool: 銷毀線程池,銷毀前要保證所有的任務(wù)已經(jīng)完成 */  int destroy_pool(pthread_pool * pool) {  //釋放所有空間 等待任務(wù)執(zhí)行完畢(join)。  //喚醒所有線程  //利用join函數(shù)回收每一個線程資源。 }  /*  add_task:給任務(wù)隊列增加任務(wù), 把do_task指向的任務(wù)(函數(shù)指針)和   arg指向的參數(shù)保存到一個任務(wù)結(jié)點,添加到pool任務(wù)隊列中。     @pool : 您要添加任務(wù)的線程池  @do_task : 您需要添加的任務(wù)(cp_file)  @arg: 您要執(zhí)行的任務(wù)的參數(shù)(文件描述符) */  int add_task(pthread_pool *pool,void*(* do_task)(void * arg), void*arg) {  //把第二個參數(shù)和第三個參數(shù)封裝成struct task     //再把它添加到 pool->task 任務(wù)隊列中去    //注意任務(wù)隊列是一個共享資源    //假如任務(wù)后要喚醒等待的線程。 }  //如果任務(wù)多的時候,往線程池中添加線程  pthread_create int add_threads(pthread_pool * pool, unsigned int num); {  //新創(chuàng)建num個線程,讓每一個線程去執(zhí)行線程調(diào)配函數(shù)    //將每一個新創(chuàng)建的線程tid,添加到pool-> tids  }  //如果任務(wù)少的時候,減少線程池中線程的數(shù)量 pthread_cancel join int remove_threads(pthread_pool * pool, unsigned int num) {  //用pthread_cancel取消num個線程   //利用pthread_join函數(shù)去回收資源。 }

pthread_pool.h

#ifndef __PTHREAD_POOL_H__ #define __PTHREAD_POOL_H__  //表示線程池中最多有多少個線程 #define MAX_ACTIVE_THREADS 20  //表示線程池中最多有多少個任務(wù) #define MAX_WAITING_TASKS 1024  //任務(wù)隊列(鏈表)上面的任務(wù)結(jié)點,只要能夠描述好一個任務(wù)就可以了, //線程會不斷地任務(wù)隊列取任務(wù) struct task  //任務(wù)結(jié)點  {  // 1. 任務(wù)結(jié)點表示的任務(wù),“函數(shù)指針”指向任務(wù)要執(zhí)行的函數(shù)(cp_file)  void*(* do_task)(void * arg);    //2. 指針,指向任務(wù)指向函數(shù)的參數(shù)(文件描述符)  void * arg;    //3. 任務(wù)結(jié)點類型的指針,指向下一個任務(wù)  struct task * next; };  struct pthread_pool //線程池的實現(xiàn) {  //一般會有如下成員   //互斥鎖,用來保護這個“任務(wù)隊列”  pthread_mutex_t lock; //互斥鎖     //線程條件變量 表示“任務(wù)隊列”是否有任務(wù)  pthread_cond_t cond; //條件變量    bool shutdown; //表示是否退出程序 bool:類型 false / true   //任務(wù)隊列(鏈表),指向第一個需要指向的任務(wù)  //所有的線程都從任務(wù)鏈表中獲取任務(wù) "共享資源"  struct task * task_list;    //線程池中有多個線程,每一個線程都有tid, 需要一個數(shù)組去保存tid  pthread_t * tids; //malloc()     //線程池中正在服役的線程數(shù),當(dāng)前線程個數(shù)  unsigned int active_threads;    //線程池任務(wù)隊列最大的任務(wù)數(shù)量  unsigned int max_waiting_tasks;    //線程池任務(wù)隊列上當(dāng)前有多少個任務(wù)  unsigned int cur_waiting_tasks;    //......  };  /*  init_pool: 線程池初始化函數(shù),初始化指定的線程池中有thread_num   個初始線程  @pool:指針,指向您要初始化的那個線程池  @threa_num: 您要初始化的線程池中開始的線程數(shù)量  返回值:    成功 0   失敗 -1 */  int init_pool(pthread_pool * pool , unsigned int threa_num);  /*  routine: 任務(wù)調(diào)配函數(shù)。   所有線程開始都執(zhí)行此函數(shù),此函數(shù)會不斷的從線程池的任務(wù)隊列   中取下任務(wù)結(jié)點,去執(zhí)行。      任務(wù)結(jié)點中包含“函數(shù)指針” h "函數(shù)參數(shù)" */  void * routine(void * arg);  /*  destroy_pool: 銷毀線程池,銷毀前要保證所有的任務(wù)已經(jīng)完成 */  int destroy_pool(pthread_pool * pool);  /*  add_task:給任務(wù)隊列增加任務(wù), 把do_task指向的任務(wù)(函數(shù)指針)和   arg指向的參數(shù)保存到一個任務(wù)結(jié)點,添加到pool任務(wù)隊列中。     @pool : 您要添加任務(wù)的線程池  @do_task : 您需要添加的任務(wù)(cp_file)  @arg: 您要執(zhí)行的任務(wù)的參數(shù)(文件描述符) */  int add_task(pthread_pool *pool,void*(* do_task)(void * arg), void*arg);  //如果任務(wù)多的時候,往線程池中添加線程  pthread_create int add_threads(pthread_pool * pool, unsigned int num);   //如果任務(wù)少的時候,減少線程池中線程的數(shù)量 pthread_cancel join int remove_threads(pthread_pool * pool, unsigned int num);  #endif

感謝你能夠認真閱讀完這篇文章,希望小編分享的“Linux C下線程池有什么用”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI