线程池搜索系统盘文件

说明:
与前两种方法类似。

线程池,根据CPU的核心来决定线程的数目。
线程池的最好线程数量:CPU核心*2
原因:
每一个CPU核心运行一条线程。*2为了可以让线程间进行切换。

区别:
(1)线程:进程中负责程序执行的执行单元。一个进程中至少有一个线程。

 

(2)多线程:解决多任务同时执行的需求,合理使用CPU资源。多线程的运行是根据CPU切换完成,如何切换由CPU决定,
因此多线程运行具有不确定性。
使用多线程的优缺点:
优点:
1)适当的提高程序的执行效率(多个线程同时执行)。
2)适当的提高了资源利用率(CPU、内存等)。
缺点:
1)占用一定的内存空间。
2)线程越多CPU的调度开销越大。
3)程序的复杂度会上升。

 

(3)
线程池:基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。
当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。

 

线程池的优点
1)避免线程的创建和销毁带来的性能开销。
2)避免大量的线程间因互相抢占系统资源导致的阻塞现象。
3}能够对线程进行简单的管理并提供定时执行、间隔执行等功能。


步骤:
1.获取计算机的CPU核数,确定线程总数。
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
g_nMaxThreadNum = (sysInfo.dwNumberOfProcessors)*2;

2.一起性创建全部线程,并激活放入容器中。
注意:一定要判断线程是否创建成功,若线程创建失败,但是线程数却+1,最后也会造成卡死。
vector <HANDLE> vecThreadHanles;
for (UINT i = 0; i < g_nMaxThreadNum; ++i)
{
HANDLE hThread=((HANDLE)_beginthreadex(NULL, 0, FindFileThread, &wstrSeachName, 0, NULL));
if (hThread == NULL)
i--;
else
vecThreadHanles.push_back(hThread);
}

3.设置手动信号量。(第二参数)
g_hPushEvent = CreateEvent(NULL, TURE,FALSE, NULL);
if (g_hPushEvent == NULL)
{
printf("Error %d", GetLastError());
return -1;
}
注意:
信号量Event
自动:只有一条线程在运行,其他线程处于等待状态

手动:全部线程一起运行,然后全部线程一起等待,

4.容器为空,没用线程,此时信号量bActive=FALSE,不可以运行线程。
若容器中有内容,允许操作线程。
当线程完成操作后,凋亡后,信号号一定为bActive = TRUE,否则线程也会卡死。

//源代码

#include "stdafx.h"
#include <Windows.h>
#include <process.h>
#include <vector>
#include <stdlib.h>
#include <iostream>
using namespace std;

    
UINT g_nMaxThreadNum = 0;            //可运行的最大线程数
long g_lWorkThreadnum = 0;
HANDLE g_hExitEvent,g_hPushEvent;    //标记可以退出程序,,,线程活跃
CRITICAL_SECTION g_cs;                //临界区
vector <wstring> g_vecFileName;        //文件夹中的文件名

UINT g_nFileNum=0,g_nNum=10;        //文件夹与文件的数目


wstring MakeStdStyle(wstring &wstrFileName)
{
    if (wstrFileName.back() != '\\')
        return wstrFileName + L"\\";
    else
        return wstrFileName;
}


unsigned _stdcall FindFileThread(void *lParam)
{
    wstring *pwstrSearchName = (wstring *)lParam,wstrTempName;
    BOOL bActive=TRUE;
    while (TRUE)
    {
        EnterCriticalSection(&g_cs);
        if (g_vecFileName.empty())
        {
            bActive = FALSE;
        }
        else
        {
            wstrTempName = g_vecFileName.back();
            g_vecFileName.pop_back();
        }
        LeaveCriticalSection(&g_cs);

        if (!bActive)
        {
            InterlockedAdd(&g_lWorkThreadnum, -1);
            if (g_lWorkThreadnum == 0)
            {
                SetEvent(g_hExitEvent);
                break;
            }
                
            ResetEvent(&g_hPushEvent);
            WaitForSingleObject(g_hPushEvent, INFINITE);
            InterlockedAdd(&g_lWorkThreadnum, 1);
            bActive = TRUE;    
            continue;
        }
        
        WIN32_FIND_DATA FileData = { 0 };
        HANDLE hFindFile = FindFirstFile((MakeStdStyle(wstrTempName) + L"*.*").c_str(), &FileData);
        if (hFindFile != INVALID_HANDLE_VALUE)
        {
            g_nFileNum++;
            do
            {
                if (wcscmp(FileData.cFileName, L".") == 0)
                {
                    continue;
                }
                if (wcscmp(FileData.cFileName, L"..") == 0)
                {
                    continue;
                }
                if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                    EnterCriticalSection(&g_cs);
                    g_vecFileName.push_back((MakeStdStyle(wstrTempName) + FileData.cFileName));
                    LeaveCriticalSection(&g_cs);
                    SetEvent(g_hPushEvent);
                }
                else
                {
                    if (wcsstr(FileData.cFileName, pwstrSearchName->c_str()) != NULL)
                    {
                        printf("文件:%ls\r\n", (MakeStdStyle(wstrTempName) + FileData.cFileName).c_str());
                    }
                    g_nNum++;
                    //bActive = TRUE;
                }

            } while (FindNextFileW(hFindFile, &FileData));
        }



    }
    return 0;
}


int _tmain(int argc, _TCHAR* argv[])
{

    DWORD dwBegin = GetTickCount();
    wstring wstrSeachName = L"ntdll";
    g_vecFileName.push_back(L"C:\\");
    InitializeCriticalSection(&g_cs);

    g_hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (g_hExitEvent == NULL)
    {
        printf("Error %d", GetLastError());
        return -1;
    }
    
    g_hPushEvent = CreateEvent(NULL, TURE,FALSE, NULL);
    if (g_hPushEvent == NULL)
    {
        printf("Error %d", GetLastError());
        return -1;
    }


    //根据CPU核心初定线程数目
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    g_nMaxThreadNum = (sysInfo.dwNumberOfProcessors)*2;
    
    g_lWorkThreadnum = g_nMaxThreadNum;

    vector <HANDLE> vecThreadHanles;
    for (UINT i = 0; i < g_nMaxThreadNum; ++i)
    {
        HANDLE hThread=((HANDLE)_beginthreadex(NULL, 0, FindFileThread, &wstrSeachName, 0, NULL));
        if (hThread == NULL)
            i--;
        else
            vecThreadHanles.push_back(hThread);
    }

    WaitForSingleObject(g_hExitEvent, INFINITE);

    /*for(auto vec_ThreadHanles : vecThreadHanles)
    {
        _endthreadex((unsigned) vec_ThreadHanles);
    }*/

    DWORD dwTime = GetTickCount() - dwBegin;
    printf("文件夹数目:%d,,文件数目:%d \n", g_nFileNum, g_nNum);
    printf("共用时%d秒 \n", dwTime/1000);
    
    DeleteCriticalSection(&g_cs);
    CloseHandle(g_hExitEvent);

    
    system("pause");
    return 0;
}

 

posted @ 2017-09-25 12:03  gd_沐辰  阅读(151)  评论(0编辑  收藏  举报