線性池的應用來源
為滿足多客戶端可同時登陸的要求,伺服器端必須實現併發工作方式。當伺服器主程式持續等待客戶端連線時,每連線上一個客戶端都需一個單獨的程式或執行緒處理客戶端的任務。但考慮到多程式對系統資源消耗大,單一執行緒存在重複建立、銷燬等動作產生過多的排程開銷,故採用線性池的方法。
線性池是一種多執行緒併發的處理形式,它就是由一堆已建立好的執行緒組成。有新任務 -> 取出空閒執行緒處理任務 -> 任務處理完成放入執行緒池等待。避免了處理短時間任務時大量的執行緒重複建立、銷燬的代價,非常適用於連續產生大量併發任務的場合。
線行池實現原理過程:
1)初始設定任務佇列(連結串列)作為緩衝機制,並初始化建立n個執行緒,加鎖去任務佇列取任務執行(多執行緒互斥)。
2)在處理任務過程中,當任務佇列為空時,所有執行緒阻塞(阻塞IO)處於空閒(wait)狀態;
3)當任務佇列加入新的任務時,佇列加鎖,然後使用條件變數喚醒(work)處於阻塞中的某一執行緒來執行任務;
4)執行完後再次返回執行緒池中成為空閒(wait)狀態,依序或等待執行下一個任務。
最後完成所有任務將執行緒池中的執行緒統一銷燬。
加入程式框架中:
main主函式下: //1.初始化執行緒池 pool_init(5); // 等待連線 while(1) { new_fd = accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size); //2.執行process,將process任務交給執行緒池 pool_add_task(process,new_fd); } void pool_init (int max_thread_num) { pool->threadid = (pthread_t *) malloc (max_thread_num * sizeof (pthread_t)); //申請堆空間 for (i = 0; i < max_thread_num; i++) //3 { pthread_create (&(pool->threadid[i]), NULL, thread_routine, NULL); //建立執行緒 儲存執行緒id } } int pool_add_task (void *(*process) (int arg), int arg) { /*構造一個新任務 初始化*/ Cthread_task *task = (Cthread_task *) malloc (sizeof (Cthread_task)); task->process = process; task->arg = arg; task->next = NULL; pthread_mutex_lock (&(pool->queue_lock)); ~~~~~~ pthread_mutex_unlock (&(pool->queue_lock)); pthread_cond_signal (&(pool->queue_ready)); //喚醒執行緒 return 0; } void * process(int arg) //讀取操作符,讀取對應的命令響應