生活随笔
收集整理的這篇文章主要介紹了
Linux系统编程——线程池
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
http://blog.csdn.net/tennysonsky/article/details/46490099#
線程池基本原理
在傳統(tǒng)服務(wù)器結(jié)構(gòu)中,常是有一個總的監(jiān)聽線程監(jiān)聽有沒有新的用戶連接服務(wù)器,每當(dāng)有一個新的用戶進(jìn)入,服務(wù)器就開啟一個新的線程用戶處理這 個用戶的數(shù)據(jù)包。這個線程只服務(wù)于這個用戶,當(dāng)用戶與服務(wù)器端關(guān)閉連接以后,服務(wù)器端銷毀這個線程。(關(guān)于并發(fā)服務(wù)器更多詳情,請看《并發(fā)服務(wù)器》)。
然而頻繁地開辟與銷毀線程極大地占用了系統(tǒng)的資源,而且在大量用戶的情況下,系統(tǒng)為了開辟和銷毀線程將浪費大量的時間和資源。線程池提供了一個解決外部大量用戶與服務(wù)器有限資源的矛盾。
線程池和傳統(tǒng)的一個用戶對應(yīng)一個線程的處理方法不同,它的基本思想就是在程序開始時就在內(nèi)存中開辟一些線程,線程的數(shù)目是固定的,他們獨自形成一個類,屏蔽了對外的操作,而服務(wù)器只需要將數(shù)據(jù)包交給線程池就可以了。當(dāng)有新的客戶請求到達(dá)時,不是新創(chuàng)建一個線程為其服務(wù),而是從“池子”中選擇一個空閑的線程為新的客戶請求服務(wù),服務(wù)完畢后,線程進(jìn)入空閑線程池中。如果沒有線程空閑的話,就將數(shù)據(jù)包暫時積累, 等待線程池內(nèi)有線程空閑以后再進(jìn)行處理。通過對多個任務(wù)重用已經(jīng)存在的線程對象,降低了對線程對象創(chuàng)建和銷毀的開銷。當(dāng)客戶請求 時,線程對象已經(jīng)存在,可以提高請求的響應(yīng)時間,從而整體地提高了系統(tǒng)服務(wù)的表現(xiàn)。
線程池應(yīng)用實例
一般來說實現(xiàn)一個線程池主要包括以下幾個組成部分:
1)線程管理器:用于創(chuàng)建并管理線程池。
2)工作線程:線程池中實際執(zhí)行任務(wù)的線程。在初始化線程時會預(yù)先創(chuàng)建好固定數(shù)目的線程在池中,這些初始化的線程一般處于空閑狀態(tài),一般不占用 CPU,占用較小的內(nèi)存空間。
3)任務(wù)接口:每個任務(wù)必須實現(xiàn)的接口,當(dāng)線程池的任務(wù)隊列中有可執(zhí)行任務(wù)時,被空閑的工作線程調(diào)去執(zhí)行(線程的閑與忙是通過互斥量實現(xiàn)的),把任務(wù)抽象出來形成接口,可以做到線程池與具體的任務(wù)無關(guān)。
4)任務(wù)隊列:用來存放沒有處理的任務(wù),提供一種緩沖機(jī)制,實現(xiàn)這種結(jié)構(gòu)有好幾種方法,常用的是隊列,主要運用先進(jìn)先出原理,另外一種是鏈表之類的數(shù)據(jù)結(jié)構(gòu),可以動態(tài)的為它分配內(nèi)存空間,應(yīng)用中比較靈活,此教程就是用到的鏈表。
什么時候需要創(chuàng)建線程池呢?簡單的說,如果一個應(yīng)用需要頻繁的創(chuàng)建和銷毀線程,而任務(wù)執(zhí)行的時間又非常短,這樣線程創(chuàng)建和銷毀的帶來的開銷就不容忽視,這時也是線程池該出場的機(jī)會了。如果線程創(chuàng)建和銷毀時間相比任務(wù)執(zhí)行時間可以忽略不計,則沒有必要使用線程池了。
線程池實現(xiàn)示例代碼如下:
thread_pool.h 的示例代碼:
[cpp]?view plaincopy
#ifndef?__THREAD_POOL_H__?? #define?__THREAD_POOL_H__?? ?? #include?<pthread.h>?? ?? ?? ? ?? typedef?void?*(*pool_task_f)(void?*arg);?? ?? ? ? ?? typedef?struct?_task{?? ????pool_task_f?process;?? ????void?*arg;??????? ????struct?_task?*next;?? }pool_task;?? ?? ? ? ?? typedef?struct?? {?? ????pthread_t?*threadid;?????????? ????int?threads_limit;???????????? ????int?destroy_flag;????????????? ????pool_task?*queue_head;???????? ????int?task_in_queue;???????????? ????pthread_mutex_t?queue_lock;??? ????pthread_cond_t?queue_ready;??? }pool_t;?? ?? ? ? ? ? ? ? ?? void?pool_init(pool_t?*pool,?int?threads_limit);?? ?? ? ? ? ? ? ?? int?pool_uninit(pool_t?*pool);?? ?? ? ? ? ? ? ? ? ?? int?pool_add_task(pool_t?*pool,?pool_task_f?process,?void?*arg);?? ?? ?? #endif??
thread_pool.c 的示例代碼:
[cpp]?view plaincopy
#include?<stdio.h>?? #include?<stdlib.h>?? #include?<pthread.h>?? #include?<assert.h>?? ?? #include?"thread_pool.h"?? ?? static?void?*pool_thread_server(void?*arg);?? ?? ? ? ? ? ? ? ?? void?pool_init(pool_t?*pool,?int?threads_limit)?? {?? ????pool->threads_limit?=?threads_limit;?? ????pool->queue_head?=?NULL;?? ????pool->task_in_queue?=?0;?? ????pool->destroy_flag?=?0;?? ?????? ????pool->threadid?=?(pthread_t?*)calloc(threads_limit,?sizeof(pthread_t));?? ????int?i?=?0;?? ?????? ????pthread_mutex_init(&(pool->queue_lock),?NULL);?? ????pthread_cond_init(&(pool->queue_ready),?NULL);?? ?????? ????for?(i?=?0;?i?<?threads_limit;?i++){?? ????????pthread_create(&(pool->threadid[i]),?NULL,?pool_thread_server,?pool);?? ????}?? ????return;?? }?? ?? ? ? ? ? ? ?? int?pool_uninit(pool_t?*pool)?? {?? ????pool_task?*head?=?NULL;?? ????int?i;?? ?????? ????pthread_mutex_lock(&(pool->queue_lock));?? ????if(pool->destroy_flag)?? ????????return?-1;?? ????pool->destroy_flag?=?1;?? ????pthread_mutex_unlock(&(pool->queue_lock));?? ?????? ????pthread_cond_broadcast(&(pool->queue_ready));?? ?????? ????for?(i?=?0;?i?<?pool->threads_limit;?i++)?? ????????pthread_join(pool->threadid[i],?NULL);?? ????free(pool->threadid);?? ?????? ????pthread_mutex_lock(&(pool->queue_lock));?? ????while(pool->queue_head?!=?NULL){?? ????????head?=?pool->queue_head;?? ????????pool->queue_head?=?pool->queue_head->next;?? ????????free(head);?? ????}?? ????pthread_mutex_unlock(&(pool->queue_lock));?? ?????? ????pthread_mutex_destroy(&(pool->queue_lock));?? ????pthread_cond_destroy(&(pool->queue_ready));?? ????return?0;?? }?? ?? ? ? ? ? ? ? ? ?? static?void?enqueue_task(pool_t?*pool,?pool_task_f?process,?void?*arg)?? {?? ????pool_task?*task?=?NULL;?? ????pool_task?*member?=?NULL;?? ?????? ????pthread_mutex_lock(&(pool->queue_lock));?? ?????? ????if(pool->task_in_queue?>=?pool->threads_limit){?? ????????printf("task_in_queue?>?threads_limit!\n");?? ????????pthread_mutex_unlock?(&(pool->queue_lock));?? ????????return;?? ????}?? ?????? ????task?=?(pool_task?*)calloc(1,?sizeof(pool_task));?? ????assert(task?!=?NULL);?? ????task->process?=?process;?? ????task->arg?=?arg;?? ????task->next?=?NULL;?? ????pool->task_in_queue++;?? ????member?=?pool->queue_head;?? ????if(member?!=?NULL){?? ????????while(member->next?!=?NULL)???? ????????????member?=?member->next;?? ????????member->next?=?task;?? ????}else{?? ????????pool->queue_head?=?task;??? ????}?? ????printf("\ttasks?%d\n",?pool->task_in_queue);?? ?????? ????pthread_cond_signal?(&(pool->queue_ready));?? ????pthread_mutex_unlock?(&(pool->queue_lock));?? }?? ?? ? ? ? ? ?? static?pool_task?*dequeue_task(pool_t?*pool)?? {?? ????pool_task?*task?=?NULL;?? ?????? ????pthread_mutex_lock(&(pool->queue_lock));?? ?????? ????if(pool->destroy_flag){?? ????????pthread_mutex_unlock(&(pool->queue_lock));?? ????????printf("thread?0x%lx?will?be?destroyed\n",?pthread_self());?? ????????pthread_exit(NULL);?? ????}?? ?????? ????if(pool->task_in_queue?==?0){?? ????????while((pool->task_in_queue?==?0)?&&?(!pool->destroy_flag)){?? ????????????printf("thread?0x%lx?is?waitting\n",?pthread_self());?? ?????????????? ????????????pthread_cond_wait(&(pool->queue_ready),?&(pool->queue_lock));?? ????????}?? ????}else{?? ?????????? ????????pool->task_in_queue--;?? ????????task?=?pool->queue_head;?? ????????pool->queue_head?=?task->next;?? ????????printf("thread?0x%lx?received?a?task\n",?pthread_self());?? ????}?? ????pthread_mutex_unlock(&(pool->queue_lock));?? ????return?task;?? }?? ?? ? ? ? ? ? ? ? ?? int?pool_add_task(pool_t?*pool,?pool_task_f?process,?void?*arg)?? {?? ????enqueue_task(pool,?process,?arg);?? ????return?0;?? }?? ?? ? ? ? ? ?? static?void?*pool_thread_server(void?*arg)?? {?? ????pool_t?*pool?=?NULL;?? ?????? ????pool?=?(pool_t?*)arg;?? ????while(1){?? ????????pool_task?*task?=?NULL;?? ????????task?=?dequeue_task(pool);?? ?????????? ????????if(task?!=?NULL){?? ????????????printf?("thread?0x%lx?is?busy\n",?pthread_self());?? ????????????task->process(task->arg);?? ????????????free(task);?? ????????????task?=?NULL;?? ????????}?? ????}?? ?????? ????pthread_exit(NULL);???? ????return?NULL;?? }??
下面是測試代碼:
[cpp]?view plaincopy
#include?<stdio.h>?? #include?<unistd.h>?? ?? #include?"thread_pool.h"?? ?? void?*task_test(void?*arg)?? {?? ????printf("\t\tworking?on?task?%d\n",?(int)arg);?? ????sleep(1);????????????? ????return?NULL;?? }?? ?? void?thread_pool_demo(void)?? {?? ????pool_t?pool;?? ????int?i?=?0;?? ?? ????pool_init(&pool,?2);?? ????sleep(1);?? ????for(i?=?0;?i?<?5;?i++){?? ????????sleep(1);?? ????????pool_add_task(&pool,?task_test,?(void?*)i);?? ????}?? ????sleep(4);?? ?? ????pool_uninit(&pool);?? }?? ?? int?main?(int?argc,?char?*argv[])?? {???? ????thread_pool_demo();?? ????return?0;?? }??
運行結(jié)果如下:
本教程示例代碼下載請點此處。
參考資料:http://blog.csdn.net/hubi0952
總結(jié)
以上是生活随笔為你收集整理的Linux系统编程——线程池的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。