线程池搜索系统盘文件
说明:
与前两种方法类似。
线程池,根据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; }