1. 程式人生 > >windows程式設計之執行緒池

windows程式設計之執行緒池

在講執行緒池之前,我們先來看下“池”是什麼意思。

“池”,我把他歸結為一大堆的資源,比如說,記憶體,執行緒,網路連線,資料庫的連線等一系列的資源,因而與之相對應的就有,記憶體池,執行緒池,網路連線池,資料庫連線池等。

執行緒池也就是一大堆的執行緒資源,它們在程式剛開始執行的時候就存在了,等需要它們的時候呢,就可以使用它們,而不必向作業系統去申請。那麼我們為何不在需要的時候再向作業系統申請呢?這是由於動態的申請執行緒資源的話,要從應用層轉到核心層,這期間花費的時間是非常慢的,如果我們要經常的使用執行緒,而採用動態申請就需要非常多的時間,這會大大降低程式的效率。因此,針對這種情況,我們就在程式執行開始時,就申請一大堆執行緒,需要的時候就從執行緒池裡邊拿,不需熬的時候就讓它們掛起。接下來看下在windows平臺下最簡單的執行緒池。

首先,MSDN提供了CreateThreadPool這個API,用於建立一個執行緒池,其宣告如下:

PTP_POOL WINAPI CreateThreadpool(
  _Reserved_ PVOID reserved<span style="white-space:pre">	</span>//作業系統保留的,必須為NULL
);
第二個是SetThreadpoolThreadMinimum,用於設定執行緒池的最小執行緒數,其宣告如下:
BOOL WINAPI SetThreadpoolThreadMinimum(
  PTP_POOL ptpp,<span style="white-space:pre">		</span>//上一個函式的返回值
  DWORD    cthrdMic<span style="white-space:pre">		</span>//執行緒池中最小的執行緒數
);
第三個是SetThreadpoolThreadMaximum,用於設定最大的執行緒數,其宣告如下:
VOID WINAPI SetThreadpoolThreadMaximum(
  PTP_POOL ptpp,<span style="white-space:pre">		</span>//第一個函式的返回值
  DWORD    cthrdMost<span style="white-space:pre">		</span>//執行緒池中最大的執行緒數
);
當我們設定完最小和最大執行緒數的時候,就可以初始化一下執行緒池的回撥環境了,回撥環境是一個TP_CALLBACK_ENVIRON結構體,我們用InitializeThreadpoolEnvironment來初始化該環境,該函式的宣告如下:
VOID InitializeThreadpoolEnvironment(
  PTP_CALLBACK_ENVIRON pcbe<span style="white-space:pre">	</span>//回撥環境地址
);
回撥環境必須指明我們的工作任務由哪個執行緒池來處理,而SetThreadpoolCallbackPool這個API就是來幹這個滴,其宣告如下:
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;
}