Linux线程(六)
Linux線程(六)
文章目錄
- Linux線程(六)
- 一、線程池
一、線程池
-
1.線程池:
-
線程池是一種使用模式。線程過多會帶來調(diào)度開銷,進(jìn)而影響緩存的局部性和整體性能。
-
而線程池維護(hù)著多個線程,等待監(jiān)督管理者分配可并發(fā)執(zhí)行的任務(wù)。這避免了在處理短時間任務(wù)時創(chuàng)建和銷毀線程的代價。
-
線程池內(nèi)部不僅能夠保證內(nèi)核的充分利用,還能防止過度調(diào)度。可線程的數(shù)量應(yīng)該取決于可用的并發(fā)處理器、處理器內(nèi)核、內(nèi)存、網(wǎng)絡(luò)socket等的數(shù)量
-
2.應(yīng)用場景:
-
需要大量的線程來完成任務(wù),且完成任務(wù)的時間比較短。
-
Web服務(wù)器完成網(wǎng)頁請求這樣的任,非常適合使用線程池來完成。因為單個任務(wù)小,而任務(wù)量巨大。
-
想象一下熱門網(wǎng)站的點擊次數(shù)和速度。但相對于長時間的任務(wù)。比如一個Telnet鏈接。線程池的優(yōu)點就不明顯了,因為Telnet會話時間比線程創(chuàng)建時間大多了
-
對性能要求比較苛刻的應(yīng)用。比如服務(wù)器同一時刻要快速響應(yīng)大量客戶的請求
-
接受突發(fā)性的大量請求,但不至于使服務(wù)器因此產(chǎn)生大量的線程應(yīng)用。突發(fā)性大量客戶請求,在沒有線程池的情況下,將產(chǎn)生大量線程,雖然理論上大部分操作系統(tǒng)線程數(shù)量數(shù)目最大值不是問題,但是短時間內(nèi)產(chǎn)生大量線程可能使內(nèi)存達(dá)到極限出現(xiàn)錯誤
-
3.線程池種類:
-
任務(wù)隊列控制的線程池模型,
-
工作線程控制的線程池模型,
-
主控線程控制的線程池模型
-
4.線程池事例:
-
創(chuàng)建固定數(shù)量的線程池,循環(huán)從任務(wù)隊列中獲取任務(wù)對象
-
獲取到任務(wù)對象后,執(zhí)行任務(wù)對象的任務(wù)接口
threadpool.hpp
#ifndef __M_POOL_H__ #define __M_POOL_H__ #include <iostream> #include <queue> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> #define MAX_THREAD 3 #define MAX_QUEUE 10class MyTask { private:int data; public:MyTask() {}~MyTask() {}void SetData(int _data){data = _data;}void Run(){int t = rand() % 5;printf("thread:%lu sleep %d sec, execute data:%d\n", pthread_self(), t, data);sleep(t);} };class MyThreadPool { private:int max_thread; //線程池中最大線程數(shù)int cur_thread; //當(dāng)前線程池中的線程數(shù)int keep_running;//用于停止線程池中線程的標(biāo)志int max_queue; //隊列的最大節(jié)點數(shù)pthread_t *tid; //線程的線程IDstd::queue<MyTask *> task_list;pthread_mutex_t mutex;pthread_cond_t empty;pthread_cond_t full;void ThreadLock(){pthread_mutex_lock(&mutex);} void ThreadUnLock(){pthread_mutex_unlock(&mutex);} void ConsumerWait(){pthread_cond_wait(&empty, &mutex);} void ConsumerNotify(){pthread_cond_signal(&empty);}void ProducterWait(){pthread_cond_wait(&full, &mutex);} void ProducterNotify(){pthread_cond_signal(&full);}bool ThreadIsRunning(){return (keep_running == 0 ? false : true);} void ThreadExit(){cur_thread--;//線程池中的線程退出時通知一下主線程printf("thread:%lu exit\n", pthread_self());ProducterNotify();pthread_exit(NULL);} bool QueueIsEmpty(){return (task_list.size() == 0 ? true : false);} bool QueueIsFull(){return (task_list.size() == max_queue ? true : false);}void PopTask(MyTask **task){*task = task_list.front();task_list.pop();return;}void PushTask(MyTask *task){task_list.push(task);}static void *thread_routine(void *arg){MyThreadPool *pthreadpool = (MyThreadPool*)arg;while(1) {pthreadpool->ThreadLock();//若當(dāng)前是運(yùn)行狀態(tài),并且沒有任務(wù)則掛起等待while(pthreadpool->QueueIsEmpty() && pthreadpool->ThreadIsRunning()) {pthreadpool->ConsumerWait();} //若當(dāng)前是非運(yùn)行狀態(tài),且沒有任務(wù)則退出線程//若當(dāng)前時非運(yùn)行狀態(tài),但是隊列中有任務(wù)則需要將任務(wù)執(zhí)行完畢后才能退出if (!pthreadpool->ThreadIsRunning() && pthreadpool->QueueIsEmpty()) {pthreadpool->ThreadUnLock();pthreadpool->ThreadExit();}//能夠走下來,則任務(wù)隊列不為空,那么獲取一個任務(wù)執(zhí)行MyTask *task;pthreadpool->PopTask(&task);pthreadpool->ProducterNotify();pthreadpool->ThreadUnLock();//執(zhí)行任務(wù),不能在鎖內(nèi),否則導(dǎo)致其它線程饑餓task->Run();} return NULL;} public:MyThreadPool(int _max_thread = MAX_THREAD, int _max_queue= MAX_QUEUE):max_thread(_max_thread), max_queue(_max_queue), cur_thread(_max_thread),keep_running(1){int i = 0;printf("create thread:%d-%d\n", max_thread, max_queue);tid = (pthread_t*)malloc(sizeof(pthread_t) * _max_thread);pthread_mutex_init(&mutex, NULL);pthread_cond_init(&full, NULL);pthread_cond_init(&empty, NULL);//創(chuàng)建固定數(shù)量的線程,等待執(zhí)行任務(wù)for(i = 0; i < _max_thread; i++) {int ret = pthread_create(&tid[i], NULL, thread_routine, (void*)this);if (ret != 0) {printf("create thread error\n");exit(0);} pthread_detach(tid[i]);} } ~MyThreadPool(){pthread_mutex_destroy(&mutex);pthread_cond_destroy(&full);pthread_cond_destroy(&empty);}//向線程池任務(wù)隊列中添加任務(wù)bool AddTaskToPool(MyTask *task){ThreadLock();while(QueueIsFull()) {ProducterWait();}PushTask(task);printf("add task to pool\n");ConsumerNotify();ThreadUnLock();return true;}void StopThreadPool(){//若已經(jīng)調(diào)用過線程池退出,則返回if (keep_running == 0) {return;} ThreadLock();keep_running = 0;//如果還有線程沒有退出,則掛起等待//等待所有線程將隊列中的所有任務(wù)都執(zhí)行完畢后并且退出while(cur_thread > 0) {ProducterWait();} ThreadUnLock();} };threadpool.cpp
#include "threadpool.hpp" int main() {MyTask task[10];int i;MyThreadPool pool;for (i = 0; i < 10; i++) {task[i].SetData(i);pool.AddTaskToPool(&task[i]);}pool.StopThreadPool();return 0; }總結(jié)
以上是生活随笔為你收集整理的Linux线程(六)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux线程(五)
- 下一篇: Linux线程(七)