平常我們使用new、malloc在堆區申請一塊記憶體,但由於每次申請的記憶體大小不一樣就會產生很多記憶體碎片,造成不好管理與浪費的情況。
記憶體池則是在真正使用記憶體之前,先申請分配一定數量的、大小相等(一般情況下)的記憶體塊留作備用。當有新的記憶體需求時,就從記憶體池中分出一部分記憶體塊,若記憶體塊不夠再繼續申請新的記憶體。這樣做的乙個顯著優點是盡量避免了記憶體碎片,使得記憶體分配效率得到提公升。
這兩個問題有一定的相似度,在物件導向程式程式設計中,物件的建立與析構都是乙個較為複雜的過程,較費時間,所以為了提高程式的執行效率盡可能減少建立和銷毀物件的次數,特別是一些很耗資源的物件建立和銷毀。
所以我們可以建立乙個程序池(執行緒池),預先放一些程序(執行緒)進去,要用的時候就直接呼叫,用完之後再把程序歸還給程序池,省下建立刪除程序的時間,不過當然就需要額外的開銷了。
利用執行緒池與程序池可以使管理程序與執行緒的工作交給系統管理,不需要程式設計師對裡面的執行緒、程序進行管理。
1、需要大量的執行緒來完成任務,且完成任務的時間比較短。 web伺服器完成網頁請求這樣的任務,使用執行緒池技術是非常合適的。因為單個任務小,而任務數量巨大,你可以想象乙個熱門**的點選次數。但對於長時間的任務,比如乙個telnet連線請求,執行緒池的優點就不明顯了。因為telnet會話時間比執行緒的建立時間大多了。
2、對效能要求苛刻的應用,比如要求伺服器迅速響應客戶請求。
3、接受突發性的大量請求,但不至於使伺服器因此產生大量執行緒的應用。突發性大量客戶請求,在沒有執行緒池情況下,將產生大量執行緒,雖然理論上大部分作業系統執行緒數目最大值不是問題,短時間內產生大量執行緒可能使記憶體到達極限,並出現"outofmemory"的錯誤。
首先說一下多執行緒的好處:多執行緒技術主要解決處理器單元內多個執行緒執行的問題,它可以顯著減少處理器單元的閒置時間,增加處理器單元的吞吐能力。
我們知道應用程式建立乙個物件,然後銷毀物件是很耗費資源的。建立執行緒,銷毀執行緒,也是如此。因此,我們就預先生成一些執行緒,等到我們使用的時候在進行排程,於是,一些"池化資源"技術就這樣的產生了。
本文所提到伺服器程式是指能夠接受客戶請求並能處理請求的程式,而不只是指那些接受網路客戶請求的網路伺服器程式。
多執行緒技術主要解決處理器單元內多個執行緒執行的問題,它可以顯著減少處理器單元的閒置時間,增加處理器單元的吞吐能力。但如果對多執行緒應用不當,會增加對單個任務的處理時間。可以舉乙個簡單的例子:
假設在一台伺服器完成一項任務的時間為t
t1 建立執行緒的時間
t3 執行緒銷毀的時間
顯然t = t1+t2+t3。注意這是乙個極度簡化的假設。
可以看出t1,t3是多執行緒本身的帶來的開銷,我們渴望減少t1,t3所用的時間,從而減少t的時間。但一些執行緒的使用者並沒有注意到這一點,所以在程式中頻繁的建立或銷毀執行緒,這導致t1和t3在t中占有相當比例。顯然這是突出了執行緒的弱點(t1,t3),而不是優點(併發性)。
執行緒池技術正是關注如何縮短或調整t1,t3時間的技術,從而提高伺服器程式效能的。它把t1,t3分別安排在伺服器程式的啟動和結束的時間段或者一些空閒的時間段,這樣在伺服器程式處理客戶請求時,不會有t1,t3的開銷了。
執行緒池不僅調整t1,t3產生的時間段,而且它還顯著減少了建立執行緒的數目。在看乙個例子:
#ifndef __thread_h#define __thread_h
#include #include #include using namespace std;
/**
* 執行任務的類,設定任務資料並執行
*/
class ctask
ctask(const string& taskname)
virtual ~ctask(){}
virtual int run() = 0;
void setdata(void* data); /** 設定任務資料 */
};
/**
* 執行緒池管理類的實現
*/
class cthreadpool
;
#endif
thread.cpp:
#include "thread.h"#include #include "stdlib.h"
void ctask::setdata(void * data)
vectorcthreadpool::m_vectasklist; //任務列表
bool cthreadpool::shutdown = false;
pthread_mutex_t cthreadpool::m_pthreadmutex = pthread_mutex_initializer;
pthread_cond_t cthreadpool::m_pthreadcond = pthread_cond_initializer;
/**
* 執行緒池管理類建構函式
*/
cthreadpool::cthreadpool(int threadnum)
/**
* 執行緒**函式
*/
void* cthreadpool::threadfunc(void* threaddata)
if (shutdown)
printf("tid %lu run\n", tid);
vector::iterator iter = m_vectasklist.begin();
/**
* 取出乙個任務並處理之
*/
ctask* task = *iter;
if (iter != m_vectasklist.end())
pthread_mutex_unlock(&m_pthreadmutex);
task->run(); /** 執行任務 */
printf("tid:%lu idle\n", tid);
}
return (void*)0;
}
/**
* 往任務佇列裡邊新增任務並發出執行緒同步訊號
*/
int cthreadpool::addtask(ctask *task)
/**
* 建立執行緒
*/
int cthreadpool::create()
return 0;
}
/**
* 停止所有執行緒
*/
int cthreadpool::stopall()
printf("now i will end all threads!!\n");
/** 喚醒所有等待執行緒,執行緒池要銷毀了 */
shutdown = true;
pthread_cond_broadcast(&m_pthreadcond);
/** 阻塞等待執行緒退出,否則就成殭屍了 */
for (int i = 0; i < m_ithreadnum; i++)
free(pthread_id);
pthread_id = null;
/** 銷毀條件變數和互斥體 */
pthread_mutex_destroy(&m_pthreadmutex);
pthread_cond_destroy(&m_pthreadcond);
return 0;
}
/**
* 獲取當前佇列中任務數
*/
int cthreadpool::gettasksize()
main.cpp:
#include "thread.h"#include #include #include class cmytask: public ctask
inline int run()
};
int main()
while(1)
}
sleep(2);
}
return 0;
}
記憶體池,程序池,執行緒池
在使用new malloc在堆區申請一塊記憶體的時候,由於每次申請的記憶體大小不一樣就會產生很多記憶體碎片,不好管理和浪費。記憶體池則是在真正使用記憶體之前,先申請分配一定數量的 大小相等的記憶體塊留作備用。當有新的記憶體需求時,就從記憶體池中分出一部分記憶體塊,若記憶體塊不夠用再 繼續申請新的記憶...
記憶體池 執行緒池 程序池
由於伺服器的硬體資源 充裕 那麼提高伺服器效能的乙個很直接的方法就是以空間換時間,即 浪費 伺服器的硬體資源,以換取其執行效率。這就是池的概念。池是一組資源的集合,這組資源在伺服器啟動之初就完全被建立並初始化,這稱為靜態資源分配。當伺服器進入正式執行階段,即開始處理客戶請求的時候,如果它需要相關的資...
記憶體池 執行緒池 程序池
首先介紹乙個概念 池化技術 池化技術就是 提前儲存大量的資源,以備不時之需以及重複使用 池化技術應用廣泛,如記憶體池,執行緒池,連線池等等。記憶體池相關的內容,建議看看 apache nginx 等開源web 伺服器的記憶體池實現。由於在實際應用當做,分配記憶體 建立程序 執行緒都會設計到一些系統呼...