日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

线程池原理及C语言实现线程池

發(fā)布時間:2023/11/30 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线程池原理及C语言实现线程池 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

備注:該線程池源碼參考自傳直播客培訓視頻配套資料;
源碼:https://pan.baidu.com/s/1zWuoE3q0KT5TUjmPKTb1lw 密碼:pp42
引言:線程池是一種多線程處理形式,大多用于高并發(fā)服務器上,它能合理有效的利用高并發(fā)服務器上的線程資源;

在Unix網(wǎng)絡編程中,線程與進程用于處理各項分支子功能,我們通常的操作是:接收消息 ==> 消息分類 ==> 線程創(chuàng)建 ==> 傳遞消息到子線程 ==> 線程分離 ==> 在子線程中執(zhí)行任務 ==> 任務結束退出;
對大多數(shù)小型局域網(wǎng)的通信來說,上述方法足夠滿足需求;但當我們的通信范圍擴大到廣域網(wǎng)或大型局域網(wǎng)通信中時,我們將面臨大量消息頻繁請求服務器;在這種情況下,創(chuàng)建與銷毀線程都已經(jīng)成為一種奢侈的開銷,特別對于嵌入式服務器來說更應保證內(nèi)存資源的合理利用;
因此,線程池技術應運而生;線程池允許一個線程可以多次復用,且每次復用的線程內(nèi)部的消息處理可以不相同,將創(chuàng)建與銷毀的開銷省去而不必來一個請求開一個線程;

結構講解:
線程池是一個抽象的概念,其內(nèi)部由任務隊列,一堆線程,管理者線程組成;
這里寫圖片描述


我們將以上圖為例,實現(xiàn)一個最基礎的線程池,接下來將分部分依次講解;講解順序為:1.線程池總體結構 2.線程數(shù)組 3.任務隊列 4.管理者線程 5.使用線程池接口的例子
一、線程池總體結構

這里講解線程池在邏輯上的結構體;看下方代碼,該結構體threadpool_t中包含線程池狀態(tài)信息,任務隊列信息以及多線程操作中的互斥鎖;在任務結構體中包含了一個可以放置多種不同任務函數(shù)的函數(shù)指針,一個傳入該任務函數(shù)的void*類型的參數(shù);
注意:在使用時需要將你的消息分類處理函數(shù)裝入任務的(*function);然后放置到任務隊列并通知空閑線程;

線程池狀態(tài)信息:描述當前線程池的基本信息,如是否開啟、最小線程數(shù)、最大線程數(shù)、存活線程數(shù)、忙線程數(shù)、待銷毀線程數(shù)等… …
任務隊列信息:描述當前任務隊列基本信息,如最大任務數(shù)、隊列不為滿條件變量、隊列不為空條件變量等… …
多線程互斥鎖:保證在同一時間點上只有一個線程在任務隊列中取任務并修改任務隊列信息、修改線程池信息;
函數(shù)指針:在打包消息階段,將分類后的消息處理函數(shù)放在(*function);
void*類型參數(shù):用于傳遞消息處理函數(shù)需要的信息;

/*任務*/
typedef struct {
?? void *(*function)(void *);
?? void *arg;
} threadpool_task_t;

/*線程池管理*/
struct threadpool_t{
?? pthread_mutex_t lock;???????????????? /* 鎖住整個結構體 */
?? pthread_mutex_t thread_counter;?????? /* 用于使用忙線程數(shù)時的鎖 */
?? pthread_cond_t? queue_not_full;?????? /* 條件變量,任務隊列不為滿 */
?? pthread_cond_t? queue_not_empty;????? /* 任務隊列不為空 */

?? pthread_t *threads;?????????????????? /* 存放線程的tid,實際上就是管理了線 數(shù)組 */
?? pthread_t admin_tid;????????????????? /* 管理者線程tid */
?? threadpool_task_t *task_queue;??????? /* 任務隊列 */

?? /*線程池信息*/
?? int min_thr_num;????????????????????? /* 線程池中最小線程數(shù) */
?? int max_thr_num;????????????????????? /* 線程池中最大線程數(shù) */
?? int live_thr_num;???????????????????? /* 線程池中存活的線程數(shù) */
?? int busy_thr_num;???????????????????? /* 忙線程,正在工作的線程 */
?? int wait_exit_thr_num;??????????????? /* 需要銷毀的線程數(shù) */

?? /*任務隊列信息*/
?? int queue_front;????????????????????? /* 隊頭 */
?? int queue_rear;?????????????????????? /* 隊尾 */
?? int queue_size;

?? /* 存在的任務數(shù) */
?? int queue_max_size;?????????????????? /* 隊列能容納的最大任務數(shù) */
?? /*線程池狀態(tài)*/
?? int shutdown;???????????????????????? /* true為關閉 */
};

???

**/*創(chuàng)建線程池*/**
threadpool_t *
threadpool_create(int min_thr_num, int max_thr_num, int queue_max_size)
{?????????????? /*? 最小線程數(shù)?????????? 最大線程數(shù)???????? 最大任務數(shù)*/
?? int i;
?? threadpool_t *pool = NULL;
?? do
?? {
????? /* 線程池空間開辟 */
????? if ((pool=(threadpool_t *)malloc(sizeof(threadpool_t))) == NULL)
????? {
??????? printf("malloc threadpool false; \n");
??????? break;? ?
????? }
????? /*信息初始化*/
????? pool->min_thr_num = min_thr_num;
????? pool->max_thr_num = max_thr_num;
????? pool->busy_thr_num = 0;
????? pool->live_thr_num = min_thr_num;
????? pool->wait_exit_thr_num = 0;
????? pool->queue_front = 0;
????? pool->queue_rear = 0;
????? pool->queue_size = 0;
????? pool->queue_max_size = queue_max_size;
????? pool->shutdown = false;

????? /* 根據(jù)最大線程數(shù),給工作線程數(shù)組開空間,清0 */
????? pool->threads = (pthread_t *)malloc(sizeof(pthread_t)*max_thr_num);
????? if (pool->threads == NULL)
????? {
???????? printf("malloc threads false;\n");
???????? break;
????? }
????? memset(pool->threads, 0, sizeof(pthread_t)*max_thr_num);

????? /* 隊列開空間 */
????? pool->task_queue =
????? (threadpool_task_t *)malloc(sizeof(threadpool_task_t)*queue_max_size);
????? if (pool->task_queue == NULL)
????? {
???????? printf("malloc task queue false;\n");
???????? break;
????? }

????? /* 初始化互斥鎖和條件變量 */
????? if ( pthread_mutex_init(&(pool->lock), NULL) != 0?????????? ||
?????????? pthread_mutex_init(&(pool->thread_counter), NULL) !=0? ||
?????? pthread_cond_init(&(pool->queue_not_empty), NULL) !=0? ||
?????? pthread_cond_init(&(pool->queue_not_full), NULL) !=0)
????? {
???????? printf("init lock or cond false;\n");
???????? break;
????? }

????? /* 啟動min_thr_num個工作線程 */
????? for (i=0; i<min_thr_num; i++)
????? {
???????? /* pool指向當前線程池? threadpool_thread函數(shù)在后面講解 */
???????? pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *)pool);
???????? printf("start thread 0x%x... \n", (unsigned int)pool->threads[i]);
????? }
????? /* 管理者線程 admin_thread函數(shù)在后面講解 */
????? pthread_create(&(pool->admin_tid), NULL, admin_thread, (void *)pool);

????? return pool;
?? } while(0);

?? /* 釋放pool的空間 */
?? threadpool_free(pool);
?? return NULL;
}

???

二、線程數(shù)組

線程數(shù)組實際上是在線程池初始化時開辟的一段存放一堆線程tid的空間,在邏輯上形成一個池,里面放置著提前創(chuàng)建的線程;這段空間中包含了正在工作的線程,等待工作的線程(空閑線程),等待被銷毀的線程,申明但沒有初始化的線程空間;
這里寫圖片描述

/*工作線程*/
void *
threadpool_thread(void *threadpool)
{
? threadpool_t *pool = (threadpool_t *)threadpool;
? threadpool_task_t task;

? while (true)
? {
??? pthread_mutex_lock(&(pool->lock));

??? /* 無任務則阻塞在 “任務隊列不為空” 上,有任務則跳出 */
??? while ((pool->queue_size == 0) && (!pool->shutdown))
??? {
?????? printf("thread 0x%x is waiting \n", (unsigned int)pthread_self());
?????? pthread_cond_wait(&(pool->queue_not_empty), &(pool->lock));

?????? /* 判斷是否需要清除線程,自殺功能 */
?????? if (pool->wait_exit_thr_num > 0)
?????? {
????????? pool->wait_exit_thr_num--;
????????? /* 判斷線程池中的線程數(shù)是否大于最小線程數(shù),是則結束當前線程 */
????????? if (pool->live_thr_num > pool->min_thr_num)
????????? {
???????????? printf("thread 0x%x is exiting \n", (unsigned int)pthread_self());
???????????? pool->live_thr_num--;
???????????? pthread_mutex_unlock(&(pool->lock));
???????????? pthread_exit(NULL);//結束線程
????????? }
?????? }
??? }

??? /* 線程池開關狀態(tài) */
??? if (pool->shutdown) //關閉線程池
??? {
?????? pthread_mutex_unlock(&(pool->lock));
?????? printf("thread 0x%x is exiting \n", (unsigned int)pthread_self());
?????? pthread_exit(NULL); //線程自己結束自己
??? }

??? //否則該線程可以拿出任務
??? task.function = pool->task_queue[pool->queue_front].function; //出隊操作
??? task.arg = pool->task_queue[pool->queue_front].arg;

??? pool->queue_front = (pool->queue_front + 1) % pool->queue_max_size;? //環(huán)型結構
??? pool->queue_size--;

??? //通知可以添加新任務
??? pthread_cond_broadcast(&(pool->queue_not_full));

??? //釋放線程鎖
??? pthread_mutex_unlock(&(pool->lock));

??? //執(zhí)行剛才取出的任務
??? printf("thread 0x%x start working \n", (unsigned int)pthread_self());
??? pthread_mutex_lock(&(pool->thread_counter));??????????? //鎖住忙線程變量
??? pool->busy_thr_num++;
??? pthread_mutex_unlock(&(pool->thread_counter));

??? (*(task.function))(task.arg);?????????????????????????? //執(zhí)行任務

??? //任務結束處理
??? printf("thread 0x%x end working \n", (unsigned int)pthread_self());
??? pthread_mutex_lock(&(pool->thread_counter));
??? pool->busy_thr_num--;
??? pthread_mutex_unlock(&(pool->thread_counter));
? }

? pthread_exit(NULL);
}

???

三、任務隊列

任務隊列的存在形式與線程數(shù)組相似;在線程池初始化時根據(jù)傳入的最大任務數(shù)開辟空間;當服務器前方后請求到來后,分類并打包消息成為任務,將任務放入任務隊列并通知空閑線程來取;不同之處在于任務隊列有明顯的先后順序,先進先出;而線程數(shù)組中的線程則是一個競爭關系去拿到互斥鎖爭取任務;
這里寫圖片描述

/*向線程池的任務隊列中添加一個任務*/
int
threadpool_add_task(threadpool_t *pool, void *(*function)(void *arg), void *arg)
{
?? pthread_mutex_lock(&(pool->lock));

?? /*如果隊列滿了,調(diào)用wait阻塞*/
?? while ((pool->queue_size == pool->queue_max_size) && (!pool->shutdown))
????? pthread_cond_wait(&(pool->queue_not_full), &(pool->lock));

?? /*如果線程池處于關閉狀態(tài)*/
?? if (pool->shutdown)
?? {
????? pthread_mutex_unlock(&(pool->lock));
????? return -1;
?? }

?? /*清空工作線程的回調(diào)函數(shù)的參數(shù)arg*/
?? if (pool->task_queue[pool->queue_rear].arg != NULL)
?? {
????? free(pool->task_queue[pool->queue_rear].arg);
????? pool->task_queue[pool->queue_rear].arg = NULL;
?? }

?? /*添加任務到任務隊列*/
?? pool->task_queue[pool->queue_rear].function = function;
?? pool->task_queue[pool->queue_rear].arg = arg;
?? pool->queue_rear = (pool->queue_rear + 1) % pool->queue_max_size;? /* 邏輯環(huán)? */
?? pool->queue_size++;

?? /*添加完任務后,隊列就不為空了,喚醒線程池中的一個線程*/
?? pthread_cond_signal(&(pool->queue_not_empty));
?? pthread_mutex_unlock(&(pool->lock));

?? return 0;
}

???

四、管理者線程

作為線程池的管理者,該線程的主要功能包括:檢查線程池內(nèi)線程的存活狀態(tài),工作狀態(tài);負責根據(jù)服務器當前的請求狀態(tài)去動態(tài)的增加或刪除線程,保證線程池中的線程數(shù)量維持在一個合理高效的平衡上;
說到底,它就是一個單獨的線程,定時的去檢查,根據(jù)我們的一個維持平衡算法去增刪線程;

/*管理線程*/
void *
admin_thread(void *threadpool)
{
?? int i;
?? threadpool_t *pool = (threadpool_t *)threadpool;
?? while (!pool->shutdown)
?? {
????? printf("admin -----------------\n");
????? sleep(DEFAULT_TIME);???????????????????????????? /*隔一段時間再管理*/
????? pthread_mutex_lock(&(pool->lock));?????????????? /*加鎖*/
????? int queue_size = pool->queue_size;?????????????? /*任務數(shù)*/
????? int live_thr_num = pool->live_thr_num;?????????? /*存活的線程數(shù)*/
????? pthread_mutex_unlock(&(pool->lock));???????????? /*解鎖*/

????? pthread_mutex_lock(&(pool->thread_counter));
????? int busy_thr_num = pool->busy_thr_num;?????????? /*忙線程數(shù)*/ ?
????? pthread_mutex_unlock(&(pool->thread_counter));

????? printf("admin busy live -%d--%d-\n", busy_thr_num, live_thr_num);
????? /*創(chuàng)建新線程 實際任務數(shù)量大于 最小正在等待的任務數(shù)量,存活線程數(shù)小于最大線程數(shù)*/
????? if (queue_size >= MIN_WAIT_TASK_NUM && live_thr_num <= pool->max_thr_num)
????? {
???????? printf("admin add-----------\n");
???????? pthread_mutex_lock(&(pool->lock));
???????? int add=0;

???????? /*一次增加 DEFAULT_THREAD_NUM 個線程*/
???????? for (i=0; i<pool->max_thr_num && add<DEFAULT_THREAD_NUM
????????????? && pool->live_thr_num < pool->max_thr_num; i++)
???????? {
??????????? if (pool->threads[i] == 0 || !is_thread_alive(pool->threads[i]))
?????????? {
????????????? pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *)pool);
????????????? add++;
????????????? pool->live_thr_num++;
????????????? printf("new thread -----------------------\n");
?????????? }
???????? }

???????? pthread_mutex_unlock(&(pool->lock));
????? }

????? /*銷毀多余的線程 忙線程x2 都小于 存活線程,并且存活的大于最小線程數(shù)*/
????? if ((busy_thr_num*2) < live_thr_num? &&? live_thr_num > pool->min_thr_num)
????? {
???????? // printf("admin busy --%d--%d----\n", busy_thr_num, live_thr_num);
???????? /*一次銷毀DEFAULT_THREAD_NUM個線程*/
???????? pthread_mutex_lock(&(pool->lock));
???????? pool->wait_exit_thr_num = DEFAULT_THREAD_NUM;
???????? pthread_mutex_unlock(&(pool->lock));

???????? for (i=0; i<DEFAULT_THREAD_NUM; i++)
??????? {
?????????? //通知正在處于空閑的線程,自殺
?????????? pthread_cond_signal(&(pool->queue_not_empty));
?????????? printf("admin cler --\n");
??????? }
????? }

?? }

?? return NULL;


/*線程是否存活*/
int
is_thread_alive(pthread_t tid)
{
?? int kill_rc = pthread_kill(tid, 0);???? //發(fā)送0號信號,測試是否存活
?? if (kill_rc == ESRCH)? //線程不存在
?? {
????? return false;
?? }
?? return true;
}

???

五、釋放

/*釋放線程池*/
int
threadpool_free(threadpool_t *pool)
{
?? if (pool == NULL)
???? return -1;
?? if (pool->task_queue)
????? free(pool->task_queue);
?? if (pool->threads)
?? {
????? free(pool->threads);
????? pthread_mutex_lock(&(pool->lock));?????????????? /*先鎖住再銷毀*/
????? pthread_mutex_destroy(&(pool->lock));
????? pthread_mutex_lock(&(pool->thread_counter));
????? pthread_mutex_destroy(&(pool->thread_counter));
????? pthread_cond_destroy(&(pool->queue_not_empty));
????? pthread_cond_destroy(&(pool->queue_not_full));
?? }
?? free(pool);
?? pool = NULL;

?? return 0;
}

??

/*銷毀線程池*/
int
threadpool_destroy(threadpool_t *pool)
{
?? int i;
?? if (pool == NULL)
?? {
???? return -1;
?? }
?? pool->shutdown = true;

?? /*銷毀管理者線程*/
?? pthread_join(pool->admin_tid, NULL);

?? //通知所有線程去自殺(在自己領任務的過程中)
?? for (i=0; i<pool->live_thr_num; i++)
?? {
???? pthread_cond_broadcast(&(pool->queue_not_empty));
?? }

?? /*等待線程結束 先是pthread_exit 然后等待其結束*/
?? for (i=0; i<pool->live_thr_num; i++)
?? {
???? pthread_join(pool->threads[i], NULL);
?? }

?? threadpool_free(pool);
?? return 0;
}

??

六、接口

?? /* 線程池初始化,其管理者線程及工作線程都會啟動 */
??? threadpool_t *thp = threadpool_create(10, 100, 100);
??? printf("threadpool init ... ... \n");

?? /* 接收到任務后添加 */
?? threadpool_add_task(thp, do_work, (void *)p);

?? // ... ...

?? /* 銷毀 */
?? threadpool_destroy(thp);

??

?

總結

以上是生活随笔為你收集整理的线程池原理及C语言实现线程池的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 天天视频入口 | 久久久久高清 | 免费一级特黄毛大片 | 成都4电影免费高清 | 青青草免费公开视频 | 人妻夜夜爽天天爽 | 男人av的天堂 | 亚洲一级免费视频 | 免费在线观看不卡av | 新天堂网 | 天堂99| 超碰人人澡 | a√天堂网 | 国产成人精品在线 | 亚洲国产欧美在线人成 | 国产人人干 | 午夜影院18| 女女同性高清片免费看 | 小镇姑娘国语版在线观看免费 | 蜜桃一区二区 | 天天干视频在线观看 | 欧美人与按摩师xxxx | 国产黄色在线免费观看 | 久久国产毛片 | 国产精品一区二区三区四区五区 | 欧美激情一级精品国产 | 日本欧美不卡 | 国产无玛 | 超碰爱爱| 日韩中文一区二区 | www国产亚洲精品久久网站 | 午夜视频在线观看一区二区 | 丁香六月激情 | 99草在线视频| 日韩av手机在线观看 | 少妇视频在线播放 | 小小姑娘电影大全免费播放 | 91福利网址 | 久久国产区 | 国产欧美视频一区二区三区 | 国产精品伦一区二区三区免费看 | 黄色大片在线免费观看 | 亚洲国产毛片aaaaa无费看 | 丝袜淫脚| 日本xxxxxxxxx18| 97狠狠| 欧美中日韩在线 | 黄色在线观看av | 黄色在线资源 | 色眯眯影院 | 精品一区亚洲 | 国产毛片在线视频 | 一本加勒比北条麻妃 | 日韩在线观看第一页 | 91成年人视频 | 日本欧美久久久久免费播放网 | 欧美精品一区视频 | 最新日韩视频 | 人人干人人爽 | 久久香蕉网站 | 日日躁狠狠躁 | 亚洲黄色成人网 | 欧美精品免费一区二区 | 国产精品一二区在线观看 | 香蕉视频在线播放 | 欧美日韩国产麻豆 | 高清中文字幕在线a片 | 国产偷人妻精品一区二区在线 | 麻豆视频91| 亚洲日本网站 | 国产成年人免费视频 | www日本高清视频 | 日韩porn| 日本十八禁视频无遮挡 | 免费网站在线观看人数在哪动漫 | 岛国大片在线观看 | 无码久久精品国产亚洲av影片 | mdyd—856冲田杏梨在线 | 国产一区二区三区精品在线观看 | 色哟哟在线免费观看 | 日本高潮网站 | 国产精品无码粉嫩小泬 | 亚洲第九页 | 国产精品九一 | 国产视频在线一区 | 亚洲男人av | 一本加勒比hezyo黑人 | 日韩性欧美 | 日本理论视频 | 亚洲色图欧美 | 人妖性做爰aaaa | 日韩3区| 人人玩人人弄 | 国产黄色小视频在线观看 | 国产精品亚洲一区二区 | 性感少妇在线观看 | 亚洲AV无码片久久精品 | 欧美丰满老熟妇xxxxx性 | jizz成熟丰满日本少妇 |