執行緒池的基本原理:
在傳統伺服器中,常有乙個總監聽程序監聽有無新的使用者連線伺服器,每當有乙個新的使用者接入,伺服器就開啟乙個新的執行緒使用者處理這個使用者的資料報,這個執行緒只服務於這個使用者,當使用者與伺服器端關閉連線以後,伺服器端銷毀這個執行緒。然而,頻繁的開啟與關閉服務程序極大的占用系統資源,而且在大量使用者情況下,系統為了開闢和銷毀執行緒浪費大量時間和資源,執行緒池提供乙個解決外部大量使用者與伺服器有限資源矛盾的方法,執行緒池和傳統的乙個使用者對應乙個執行緒的處理方法不同,它的基本思想就是在程式開始時在記憶體中開闢一些執行緒,執行緒的數目是固定的,它們獨自形成乙個類,遮蔽對外的操作,而伺服器只需要將資料報交給執行緒池就可以了,當有新的客戶請求到達時,不是新建立乙個執行緒為其服務,而是從「池子」中挑選乙個空閒的執行緒為新的客戶請求服務,服務完畢後執行緒進入空閒池中,如果沒有執行緒空閒的話,就將資料報暫時積累,等待執行緒池內有執行緒空閒在做處理,通過多個任務重用已經存在的執行緒物件,降低了對執行緒的建立和銷毀的開銷,當客戶請求時執行緒物件已經存在,可以提高請求的響應時間。
如果乙個應用需要頻繁的建立和銷毀執行緒,而任務執行的時間又非常短,這樣執行緒銷毀和建立的開銷就不容小視,如果執行緒建立和銷毀的時間比起任務執行時間忽略不計,則沒必要使用執行緒池。
乙個執行緒池主要包括以下幾個部分:
1) 執行緒管理器用於建立並管理執行緒池。
2) 工作執行緒:執行緒池中實際執行任務的執行緒。在初始化過程中會預先建立好固定數目
的執行緒在池中,這些初始化執行緒一般處於空閒狀態,一般不占用cpu
,較小記憶體空間。
3)任務介面:每個任務必須實現的介面,當執行緒池的任務佇列中有可執行任務時,被空置的工作執行緒調去執行(執行緒的閒與忙是通過互斥量實現的),把任務抽象出來形成介面,可以做到執行緒池與具體任務無關。
4)任務佇列:用來存放沒有處理的任務,提供一種緩衝機制,實現這種結構有好幾種方法,常用的是佇列,主要是先入先出,另外一種是鍊錶資料結構,可以動態的為他分配記憶體空間。
下面是linux
系統下用
c語言建立的執行緒池,執行緒池會維護乙個任務鍊錶(每個
cthread_work
結構就是乙個任務),
pool_init()
預先建立好
max_thread_num
個執行緒,每個執行緒執行
thread_routine
()函式,該函式中:
while(
pool->cur_queue_size == 0)
pthread_cond_wait(&(pool->queue_ready) , &(pool->queue_lock)) ;
表示如果任務鍊錶中沒有任務,則該執行緒處於阻塞等待狀態,否則從任務中取得佇列並執行。
pool_add_write向執行緒池的任務鍊錶中加入任務,加入後呼叫
pthread_cond_signal(&
(pool->queue_ready
))喚醒乙個處於阻塞狀態的執行緒。
pool_destroy()函式用於銷毀執行緒池,執行緒池任務表中的任務不再被執行,但是正在執行的執行緒會一直把任務執行完後退出。
#include#include#include#include#include#include/* 執行緒池裡所有執行和等待的任務都是乙個cthread_worker
所有任務在煉表裡所以是鍊錶結構 */
struct cthread_worker ;
//執行緒池結構
struct cthread_pool ;
int pool_add_worker (void *(*process)(void *arg) , void *arg) ;
void *thread_routine (void *arg) ;
//共享資源
static struct cthread_pool *pool = null ;
void pool_init (int thread_max_num) }
//向執行緒池中加入任務
int pool_add_worker (void *(*process) (void *arg) , void *arg)
member->next = newwork ;
} else
assert(pool->queue_head != null) ;
pool->cur_queue_size++ ;
pthread_mutex_unlock(&(pool->queue_lock)) ;
//等待佇列中有任務喚醒乙個等待執行緒, 如果所有執行緒都在忙碌,這句沒有任何作用
pthread_cond_signal(&(pool->queue_ready)) ;
return 0;
}/*銷毀執行緒池,等待佇列中的任務不再被執行,但正在執行的執行緒會一直把任務執行完後退出*/
int pool_destroy ()
free(pool->threadid) ;
//銷毀等待佇列
struct cthread_work *head = null ;
while(pool ->queue_head != null)
//銷毀條件變數和互斥量
pthread_mutex_destroy(&(pool->queue_lock)) ;
pthread_cond_destroy(&(pool->queue_ready));
free(pool) ;
//銷毀後指標置空
pool = null ;
return 0;
}void* thread_routine(void *arg)
//執行緒池要銷毀了
if (pool -> shutdown)
printf("thread %u is starting to work \n", (unsigned int)pthread_self()) ;
assert (pool->cur_queue_size != 0) ;
assert(pool->queue_head != null) ;
//等待佇列長度減一,並取出煉表頭元素
pool->cur_queue_size -- ;
struct cthread_worker *worker = pool->queue_head ;
pool->queue_head = worker->next ;
pthread_mutex_unlock(&(pool->queue_lock)) ;
//執行任務
(*(worker->process)) (worker->arg ) ;
free(worker) ;
worker = null;
}}
void * myprocess (void *arg)
int main (int argc, char **argv)
//等待所有任務完成
執行緒池學習
threadpoolexecutor int corepoolsize,int maximumpoolsize,long keepalivetime,timeunit unit,blockingqueueworkqueue,threadfactory threadfactory,rejectedex...
執行緒池學習
三 threadpoolexecutor 四 擴充套件執行緒池 總結在使用所執行緒進行開發時,為了避免系統頻繁地建立和銷毀執行緒,我們可以使用執行緒池技術。executors類扮演著執行緒工廠的角色,使用該類的靜態方法可以獲取特點功能的執行緒池。該方法返回固定執行緒數量的執行緒池。linkedblo...
執行緒池學習
執行緒池是一種多執行緒處理形式,處理過程中將任務新增到佇列,然後在建立執行緒後自動啟動這些任務。1.減少在建立和銷毀執行緒上所花的時間以及系統資源的開銷 2.避免因系統建立大量執行緒而導致消耗完系統記憶體的情況出現 這裡模擬資料庫連線池,這種 池 的作用一般就是兩點 1 需要大量的執行緒來完成任務,...