• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            VC實(shí)現(xiàn)線程池

            ??????這兩天在做關(guān)于網(wǎng)絡(luò)蜘蛛的程序,希望可以通過線程池來提高程序的性能,網(wǎng)上搜索了一下,看到這方面的東西還不少,跟大家分享一下!~有許多應(yīng)用程序創(chuàng)建的線程花費(fèi)了大量時(shí)間在睡眠狀態(tài)來等待事件的發(fā)生。還有一些線程進(jìn)入睡眠狀態(tài)后定期被喚醒以輪詢工作方式來改變或者更新狀態(tài)信息。線程池可以讓你更有效地使用線程,它為你的應(yīng)用程序提供一個(gè)由系統(tǒng)管理的工作者線程池。至少會(huì)有一個(gè)線程來監(jiān)聽放到線程池的所有等待操作,當(dāng)?shù)却僮魍瓿珊螅€程池中將會(huì)有一個(gè)工作者線程來執(zhí)行相應(yīng)的回調(diào)函數(shù)。
            ? 你也可以把沒有等待操作的工作項(xiàng)目放到線程池中,用QueueUserWorkItem函數(shù)來完成這個(gè)工作,把要執(zhí)行的工作項(xiàng)目函數(shù)通過一個(gè)參數(shù)傳遞給線程池。工作項(xiàng)目被放到線程池中后,就不能再取消了。
            ? Timer-queue timers和Registered wait operations也使用線程池來實(shí)現(xiàn)。他們的回調(diào)函數(shù)也放在線程池中。你也可以用BindIOCompletionCallback函數(shù)來投遞一個(gè)異步IO操作,在IO完成端口上,回調(diào)函數(shù)也是由線程池線程來執(zhí)行。
            ? 當(dāng)?shù)谝淮握{(diào)用QueueUserWorkItem函數(shù)或者BindIOCompletionCallback函數(shù)的時(shí)候,線程池被自動(dòng)創(chuàng)建,或者Timer-queue timers或者Registered wait operations放入回調(diào)函數(shù)的時(shí)候,線程池也可以被創(chuàng)建。線程池可以創(chuàng)建的線程數(shù)量不限,僅受限于可用的內(nèi)存,每一個(gè)線程使用默認(rèn)的初始堆棧大小,運(yùn)行在默認(rèn)的優(yōu)先級(jí)上。
            ? 線程池中有兩種類型的線程:IO線程和非IO線程。IO線程等待在可告警狀態(tài),工作項(xiàng)目作為APC放到IO線程中。如果你的工作項(xiàng)目需要線程執(zhí)行在可警告狀態(tài),你應(yīng)該將它放到IO線程。
            ? 非IO工作者線程等待在IO完成端口上,使用非IO線程比IO線程效率更高,也就是說,只要有可能的話,盡量使用非IO線程。IO線程和非IO線程在異步IO操作沒有完成之前都不會(huì)退出。然而,不要在非IO線程中發(fā)出需要很長時(shí)間才能完成的異步IO請(qǐng)求。
            ? 正確使用線程池的方法是,工作項(xiàng)目函數(shù)以及它將會(huì)調(diào)用到的所有函數(shù)都必須是線程池安全的。安全的函數(shù)不應(yīng)該假設(shè)線程是一次性線程的或者是永久線程。一般來說,應(yīng)該避免使用線程本地存儲(chǔ)和發(fā)出需要永久線程的異步IO調(diào)用,比如說RegNotifyChangeKeyValue函數(shù)。如果需要在永久線程中執(zhí)行這樣的函數(shù)的話,可以給QueueUserWorkItem傳遞一個(gè)選項(xiàng)WT_EXECUTEINPERSISTENTTHREAD。
            ? 注意,線程池不能兼容COM的單線程套間(STA)模型。
            ?
            ? ????為了更深入地講解操作系統(tǒng)實(shí)現(xiàn)的線程池的優(yōu)越性,我們首先嘗試著自己實(shí)現(xiàn)一個(gè)簡單的線程池模型。
            ?
            ? ????代碼如下:
            ??/************************************************************************/
            ??
            /*?Test?Our?own?thread?pool.????????????????????????????????????????????*/
            ??
            /************************************************************************/
            ??
            ??typedef?
            struct?_THREAD_POOL
            ??
            {
            ??????HANDLE?QuitEvent;
            ??????HANDLE?WorkItemSemaphore;
            ??
            ??????LONG?WorkItemCount;
            ??????LIST_ENTRY?WorkItemHeader;
            ??????CRITICAL_SECTION?WorkItemLock;
            ??
            ??????LONG?ThreadNum;
            ??????HANDLE?
            *ThreadsArray;
            ??
            ??}
            THREAD_POOL,?*PTHREAD_POOL;
            ??
            ??typedef?VOID?(
            *WORK_ITEM_PROC)(PVOID?Param);
            ??
            ??typedef?
            struct?_WORK_ITEM
            ??
            {
            ??????LIST_ENTRY?List;
            ??
            ??????WORK_ITEM_PROC?UserProc;
            ??????PVOID?UserParam;
            ??????
            ??}
            WORK_ITEM,?*PWORK_ITEM;
            ??
            ??
            ??DWORD?WINAPI?WorkerThread(PVOID?pParam)
            ??
            {
            ??????PTHREAD_POOL?pThreadPool?
            =?(PTHREAD_POOL)pParam;
            ??????HANDLE?Events[
            2];
            ??????
            ??????Events[
            0]?=?pThreadPool->QuitEvent;
            ??????Events[
            1]?=?pThreadPool->WorkItemSemaphore;
            ??
            ??????
            for(;;)
            ??????
            {
            ??????????DWORD?dwRet?
            =?WaitForMultipleObjects(2,?Events,?FALSE,?INFINITE);
            ??
            ??????????
            if(dwRet?==?WAIT_OBJECT_0)
            ??????????????
            break;
            ??
            ??????????
            //
            ??????????
            //?execute?user's?proc.
            ??????????
            //
            ??
            ??????????
            else?if(dwRet?==?WAIT_OBJECT_0?+1)
            ??????????
            {
            ??????????????PWORK_ITEM?pWorkItem;
            ??????????????PLIST_ENTRY?pList;
            ??
            ??????????????EnterCriticalSection(
            &pThreadPool->WorkItemLock);
            ??????????????_ASSERT(
            !IsListEmpty(&pThreadPool->WorkItemHeader));
            ??????????????pList?
            =?RemoveHeadList(&pThreadPool->WorkItemHeader);
            ??????????????LeaveCriticalSection(
            &pThreadPool->WorkItemLock);
            ??
            ??????????????pWorkItem?
            =?CONTAINING_RECORD(pList,?WORK_ITEM,?List);
            ??????????????pWorkItem
            ->UserProc(pWorkItem->UserParam);
            ??
            ??????????????InterlockedDecrement(
            &pThreadPool->WorkItemCount);
            ??????????????free(pWorkItem);
            ??????????}

            ??
            ??????????
            else
            ??????????
            {
            ??????????????_ASSERT(
            0);
            ??????????????
            break;
            ??????????}

            ??????}

            ??
            ??????
            return?0;
            ??}

            ??
            ??BOOL?InitializeThreadPool(PTHREAD_POOL?pThreadPool,?LONG?ThreadNum)
            ??
            {
            ??????pThreadPool
            ->QuitEvent?=?CreateEvent(NULL,?TRUE,?FALSE,?NULL);
            ??????pThreadPool
            ->WorkItemSemaphore?=?CreateSemaphore(NULL,?0,?0x7FFFFFFF,?NULL);
            ??????pThreadPool
            ->WorkItemCount?=?0;
            ??????InitializeListHead(
            &pThreadPool->WorkItemHeader);
            ??????InitializeCriticalSection(
            &pThreadPool->WorkItemLock);
            ??????pThreadPool
            ->ThreadNum?=?ThreadNum;
            ??????pThreadPool
            ->ThreadsArray?=?(HANDLE*)malloc(sizeof(HANDLE)?*?ThreadNum);
            ??
            ??????
            for(int?i=0;?i<ThreadNum;?i++)
            ??????
            {
            ??????????pThreadPool
            ->ThreadsArray[i]?=?CreateThread(NULL,?0,?WorkerThread,?pThreadPool,?0,?NULL);
            ??????}

            ??
            ??????
            return?TRUE;
            ??}

            ??
            ??VOID?DestroyThreadPool(PTHREAD_POOL?pThreadPool)
            ??
            {
            ??????SetEvent(pThreadPool
            ->QuitEvent);
            ??
            ??????
            for(int?i=0;?i<pThreadPool->ThreadNum;?i++)
            ??????
            {
            ??????????WaitForSingleObject(pThreadPool
            ->ThreadsArray[i],?INFINITE);
            ??????????CloseHandle(pThreadPool
            ->ThreadsArray[i]);
            ??????}

            ??
            ??????free(pThreadPool
            ->ThreadsArray);
            ??
            ??????CloseHandle(pThreadPool
            ->QuitEvent);
            ??????CloseHandle(pThreadPool
            ->WorkItemSemaphore);
            ??????DeleteCriticalSection(
            &pThreadPool->WorkItemLock);
            ??
            ??????
            while(!IsListEmpty(&pThreadPool->WorkItemHeader))
            ??????
            {
            ??????????PWORK_ITEM?pWorkItem;
            ??????????PLIST_ENTRY?pList;
            ??????????
            ??????????pList?
            =?RemoveHeadList(&pThreadPool->WorkItemHeader);
            ??????????pWorkItem?
            =?CONTAINING_RECORD(pList,?WORK_ITEM,?List);
            ??????????
            ??????????free(pWorkItem);
            ??????}

            ??}

            ??
            ??BOOL?PostWorkItem(PTHREAD_POOL?pThreadPool,?WORK_ITEM_PROC?UserProc,?PVOID?UserParam)
            ??
            {
            ??????PWORK_ITEM?pWorkItem?
            =?(PWORK_ITEM)malloc(sizeof(WORK_ITEM));
            ??????
            if(pWorkItem?==?NULL)
            ??????????
            return?FALSE;
            ??
            ??????pWorkItem
            ->UserProc?=?UserProc;
            ??????pWorkItem
            ->UserParam?=?UserParam;
            ??
            ??????EnterCriticalSection(
            &pThreadPool->WorkItemLock);
            ??????InsertTailList(
            &pThreadPool->WorkItemHeader,?&pWorkItem->List);
            ??????LeaveCriticalSection(
            &pThreadPool->WorkItemLock);
            ??
            ??????InterlockedIncrement(
            &pThreadPool->WorkItemCount);
            ???????ReleaseSemaphore(pThreadPool
            ->WorkItemSemaphore,?1,?NULL);
            ??
            ??????
            return?TRUE;
            ??}

            ??
            ??VOID?UserProc1(PVOID?dwParam)
            ??
            {
            ??????WorkItem(dwParam);
            ??}

            ??
            ??
            void?TestSimpleThreadPool(BOOL?bWaitMode,?LONG?ThreadNum)
            ??
            {
            ??????THREAD_POOL?ThreadPool;????
            ??????InitializeThreadPool(
            &ThreadPool,?ThreadNum);
            ??????
            ??????CompleteEvent?
            =?CreateEvent(NULL,?FALSE,?FALSE,?NULL);
            ??????BeginTime?
            =?GetTickCount();
            ??????ItemCount?
            =?20;
            ??
            ??????
            for(int?i=0;?i<20;?i++)
            ??????
            {
            ??????????PostWorkItem(
            &ThreadPool,?UserProc1,?(PVOID)bWaitMode);
            ??????}

            ??????
            ??????WaitForSingleObject(CompleteEvent,?INFINITE);
            ??????CloseHandle(CompleteEvent);
            ??
            ??????DestroyThreadPool(
            &ThreadPool);
            ??}

            ??????我們把工作項(xiàng)目放到一個(gè)隊(duì)列中,用一個(gè)信號(hào)量通知線程池,線程池中任意一個(gè)線程取出工作項(xiàng)目來執(zhí)行,執(zhí)行完畢之后,線程返回線程池,繼續(xù)等待新的工作項(xiàng)目。
            ??????線程池中線程的數(shù)量是固定的,預(yù)先創(chuàng)建好的,永久的線程,直到銷毀線程池的時(shí)候,這些線程才會(huì)被銷毀。
            ??????線程池中線程獲得工作項(xiàng)目的機(jī)會(huì)是均等的,隨機(jī)的,并沒有特別的方式保證哪一個(gè)線程具有特殊的優(yōu)先獲得工作項(xiàng)目的機(jī)會(huì)。
            ??????而且,同一時(shí)刻可以并發(fā)運(yùn)行的線程數(shù)目沒有任何限定。事實(shí)上,在我們的執(zhí)行計(jì)算任務(wù)的演示代碼中,所有的線程都并發(fā)執(zhí)行。
            ??????下面,我們?cè)賮砜匆幌拢瓿赏瑯拥娜蝿?wù),系統(tǒng)提供的線程池是如何運(yùn)作的。
            ??
            ??
            /************************************************************************/
            ??
            /*?QueueWorkItem?Test.??????????????????????????????????????????????????*/
            ??
            /************************************************************************/
            ??
            ??DWORD?BeginTime;
            ??LONG??ItemCount;
            ??HANDLE?CompleteEvent;
            ??
            ??
            int?compute()
            ??
            {
            ??????srand(BeginTime);
            ??
            ??????
            for(int?i=0;?i<20?*1000?*?1000;?i++)
            ??????????rand();
            ??
            ??????
            return?rand();
            ??}

            ??
            ??DWORD?WINAPI?WorkItem(LPVOID?lpParameter)
            ??
            {
            ??????BOOL?bWaitMode?
            =?(BOOL)lpParameter;
            ??
            ??????
            if(bWaitMode)
            ??????????Sleep(
            1000);
            ??????
            else
            ??????????compute();
            ??
            ??????
            if(InterlockedDecrement(&ItemCount)?==?0)
            ??????
            {
            ??????????printf(
            "Time?total?%d?second.\n",?GetTickCount()?-?BeginTime);
            ??????????SetEvent(CompleteEvent);
            ??????}

            ??
            ??????
            return?0;
            ??}

            ??
            ??
            void?TestWorkItem(BOOL?bWaitMode,?DWORD?Flag)
            ??
            {
            ??????CompleteEvent?
            =?CreateEvent(NULL,?FALSE,?FALSE,?NULL);
            ??????BeginTime?
            =?GetTickCount();
            ??????ItemCount?
            =?20;
            ??????
            ??????
            for(int?i=0;?i<20;?i++)
            ??????
            {
            ??????????QueueUserWorkItem(WorkItem,?(PVOID)bWaitMode,?Flag);
            ??????}
            ????
            ??
            ??????WaitForSingleObject(CompleteEvent,?INFINITE);
            ??????CloseHandle(CompleteEvent);
            ??}
            ????? 很簡單,是吧?我們僅需要關(guān)注于我們的回調(diào)函數(shù)即可。但是與我們的簡單模擬來比,系統(tǒng)提供的線程池有著更多的優(yōu)點(diǎn)。
            ????? 首先,線程池中線程的數(shù)目是動(dòng)態(tài)調(diào)整的,其次,線程池利用IO完成端口的特性,它可以限制并發(fā)運(yùn)行的線程數(shù)目,默認(rèn)情況下,將會(huì)限制為CPU的數(shù)目,這可以減少線程切換。它挑選最近執(zhí)行過的線程再次投入執(zhí)行,從而避免了不必要的線程切換。
            ????? 系統(tǒng)提供的線程池背后的策略,我們下一節(jié)繼續(xù)再談。
            ?
            ? 參考書目
            ?
            ? 1,??? MSDN Library
            ? 2,??? 《Windows高級(jí)編程指南》
            ? 3,??? 《Windows核心編程》
            ? 4,??? 《Windows 2000 設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)指南》

            posted on 2006-04-14 20:56 楊粼波 閱讀(24437) 評(píng)論(10)  編輯 收藏 引用 所屬分類: 文章收藏

            評(píng)論

            # re: VC實(shí)現(xiàn)線程池 2007-05-08 11:31 artcpp

            十分感謝!看后受益多多!!  回復(fù)  更多評(píng)論   

            # re: VC實(shí)現(xiàn)線程池 2007-07-07 10:09 lbblscy

            同上!  回復(fù)  更多評(píng)論   

            # re: VC實(shí)現(xiàn)線程池 2008-05-09 09:47 asf

            不錯(cuò),謝謝  回復(fù)  更多評(píng)論   

            # re: VC實(shí)現(xiàn)線程池 2008-11-03 18:14 胖鼠鼠

            謝謝,:)  回復(fù)  更多評(píng)論   

            # re: VC實(shí)現(xiàn)線程池 2009-07-09 22:57 shuizhiyun

            從頭到尾仔細(xì)看了一遍,沒有看太明白,待會(huì)兒再看一遍  回復(fù)  更多評(píng)論   

            # re: VC實(shí)現(xiàn)線程池 2012-02-28 10:49 wzw200

            很想 很想學(xué)習(xí) 怎么沒有注呢   回復(fù)  更多評(píng)論   

            # re: VC實(shí)現(xiàn)線程池 2012-06-19 09:52 宇宙鋒

            看了一遍沒完全明白,應(yīng)該有適當(dāng)?shù)淖⑨尩模?nbsp; 回復(fù)  更多評(píng)論   

            # re: VC實(shí)現(xiàn)線程池 2012-07-29 11:12 Linex

            額,我也覺得沒看明白,感覺講解的還是不夠透徹啊,或者咱水平低了點(diǎn)。。。  回復(fù)  更多評(píng)論   

            # re: VC實(shí)現(xiàn)線程池 2013-02-27 14:55 pengshuangqi

            這個(gè)人在裝B  回復(fù)  更多評(píng)論   

            # re: VC實(shí)現(xiàn)線程池 2014-05-20 14:25 VC

            寫得不錯(cuò),以簡單的方式實(shí)現(xiàn)了基本的線程池  回復(fù)  更多評(píng)論   

            97久久超碰成人精品网站| 久久精品中文无码资源站| 亚洲午夜久久久久久噜噜噜| 久久午夜夜伦鲁鲁片免费无码影视| 欧美久久一区二区三区| 国产亚洲精久久久久久无码77777 国产亚洲精品久久久久秋霞 | 久久精品国产亚洲5555| 亚洲中文字幕伊人久久无码| 久久香综合精品久久伊人| 国产亚洲色婷婷久久99精品91| 国产精品亚洲综合久久| av午夜福利一片免费看久久| 久久久无码精品午夜| 久久国产免费观看精品| 思思久久精品在热线热| 91亚洲国产成人久久精品网址| 青青草原综合久久大伊人| 日本三级久久网| 久久久久亚洲av无码专区导航| 久久免费99精品国产自在现线 | 久久精品国产91久久麻豆自制| 欧美麻豆久久久久久中文| 色综合久久久久网| 久久综合给合久久狠狠狠97色| 久久综合精品国产一区二区三区 | 久久久久久久综合日本| 99久久er这里只有精品18| 国产亚州精品女人久久久久久 | 国产精品熟女福利久久AV| 色婷婷久久综合中文久久蜜桃av| 人妻少妇精品久久| 久久精品这里只有精99品| 777久久精品一区二区三区无码| 久久天天躁狠狠躁夜夜96流白浆 | 久久综合给合久久狠狠狠97色| 欧美亚洲国产精品久久| 伊人 久久 精品| 亚洲婷婷国产精品电影人久久 | 国产精品亚洲美女久久久| 91精品国产高清久久久久久国产嫩草| 久久水蜜桃亚洲av无码精品麻豆 |