windows程式設計之執行緒池
阿新 • • 發佈:2019-02-13
在講執行緒池之前,我們先來看下“池”是什麼意思。
“池”,我把他歸結為一大堆的資源,比如說,記憶體,執行緒,網路連線,資料庫的連線等一系列的資源,因而與之相對應的就有,記憶體池,執行緒池,網路連線池,資料庫連線池等。
執行緒池也就是一大堆的執行緒資源,它們在程式剛開始執行的時候就存在了,等需要它們的時候呢,就可以使用它們,而不必向作業系統去申請。那麼我們為何不在需要的時候再向作業系統申請呢?這是由於動態的申請執行緒資源的話,要從應用層轉到核心層,這期間花費的時間是非常慢的,如果我們要經常的使用執行緒,而採用動態申請就需要非常多的時間,這會大大降低程式的效率。因此,針對這種情況,我們就在程式執行開始時,就申請一大堆執行緒,需要的時候就從執行緒池裡邊拿,不需熬的時候就讓它們掛起。接下來看下在windows平臺下最簡單的執行緒池。
首先,MSDN提供了CreateThreadPool這個API,用於建立一個執行緒池,其宣告如下:
PTP_POOL WINAPI CreateThreadpool(
_Reserved_ PVOID reserved<span style="white-space:pre"> </span>//作業系統保留的,必須為NULL
);
第二個是SetThreadpoolThreadMinimum,用於設定執行緒池的最小執行緒數,其宣告如下:
第三個是SetThreadpoolThreadMaximum,用於設定最大的執行緒數,其宣告如下:BOOL WINAPI SetThreadpoolThreadMinimum( PTP_POOL ptpp,<span style="white-space:pre"> </span>//上一個函式的返回值 DWORD cthrdMic<span style="white-space:pre"> </span>//執行緒池中最小的執行緒數 );
VOID WINAPI SetThreadpoolThreadMaximum(
PTP_POOL ptpp,<span style="white-space:pre"> </span>//第一個函式的返回值
DWORD cthrdMost<span style="white-space:pre"> </span>//執行緒池中最大的執行緒數
);
當我們設定完最小和最大執行緒數的時候,就可以初始化一下執行緒池的回撥環境了,回撥環境是一個TP_CALLBACK_ENVIRON結構體,我們用InitializeThreadpoolEnvironment來初始化該環境,該函式的宣告如下:
回撥環境必須指明我們的工作任務由哪個執行緒池來處理,而SetThreadpoolCallbackPool這個API就是來幹這個滴,其宣告如下:VOID InitializeThreadpoolEnvironment( PTP_CALLBACK_ENVIRON pcbe<span style="white-space:pre"> </span>//回撥環境地址 );
VOID SetThreadpoolCallbackPool(
PTP_CALLBACK_ENVIRON pcbe,<span style="white-space:pre"> </span>//回撥環境地址
PTP_POOL ptpp<span style="white-space:pre"> </span>//第一個函式的返回值
);
最後呢,將一個工作任務新增到執行緒池的佇列中呢,需要呼叫TrySubmitThreadpoolCallback,其宣告如下:
BOOL WINAPI TrySubmitThreadpoolCallback(
PTP_SIMPLE_CALLBACK pfns,<span style="white-space:pre"> </span>//該參為我們的工作任務函式名,稍後介紹
PVOID pv,<span style="white-space:pre"> </span>//該參為我們工作任務函式的第二個引數傳遞過來的
PTP_CALLBACK_ENVIRON pcbe<span style="white-space:pre"> </span>//回撥環境地址
);
為了讓執行緒池一非同步的方式執行我們的工作任務函式呢,我們需要定義一個具有以下原型的函式,格式不能改,名字可改:
VOID CALLBACK SimpleCallback(
PTP_CALLBACK_INSTANCE Instance,
PVOID Context
);
下面是以上的測試程式碼:
#include <windows.h>
void CALLBACK test1(PTP_CALLBACK_INSTANCE instance, PVOID context)
{
printf("Pool thread %d is running test1...\n", GetCurrentThreadId());
return;
}
void CALLBACK test2(PTP_CALLBACK_INSTANCE instance, PVOID context)
{
printf("Pool thread %d is running test2...\n", GetCurrentThreadId());
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
// 建立執行緒池
PTP_POOL pool = CreateThreadpool(0);
// 設定 執行緒池內最小有1個執行緒
SetThreadpoolThreadMinimum(pool, 1);
// 設定 最多有10個執行緒
SetThreadpoolThreadMaximum(pool, 10);
TP_CALLBACK_ENVIRON env;
//初始化執行緒回撥環境
InitializeThreadpoolEnvironment(&env);
SetThreadpoolCallbackPool(&env, pool);
//將test1任務新增到執行緒池佇列中
TrySubmitThreadpoolCallback(test1, 0, &env);
//將test2任務新增到執行緒池佇列中
TrySubmitThreadpoolCallback(test2, 0, &env);
system("pause");
return 0;
}