字符串处理算法(五)多线程实现代码行数统计。[风林火山]
实现如下:
//线程函数DWORD WINAPI ReadFileThread(LPVOID lpParam); DWORD WINAPI WorkThread(LPVOID lpParam); //线程句柄DWORD g_dwReadFileThreadID; DWORD g_dwTaskThread;DWORD g_dwWorkThread[MAX_WORKTHREAD];//事件句柄HANDLE g_EventReadFileHandle;HANDLE g_EventReadFinishHandle;//临界区CRITICAL_SECTION g_cs;CRITICAL_SECTION g_MsgQueue;CRITICAL_SECTION g_task;CRITICAL_SECTION g_MsgMap;//数据map<int, int>m_task;std::deque<int> m_MsgQueue;std::deque<int> m_FileQueue;//任务队列std::map<int, T_CodeFileMsg*> m_FileMsgMap;//处理文件与文件行数信息int WorkThreadCout = 0;int nTotalTaskCount =0;int nWorkTaslCount=0;int nTaskBeginTime;int nReadFileFinish=0;int nInitCount= 0;int nWorkFlag = 0;bool bRunFlag = TRUE;char g_workPath[MAX_LEN];bool bReadFileFlag=TRUE;int g_nTaskId=0;int main(){ int i;cout << "#####代码行数统计测试开始#####" <<endl;cout << "Main thread is running." << endl; //初始化临界区InitializeCriticalSection(&g_cs);InitializeCriticalSection(&g_MsgQueue);InitializeCriticalSection(&g_MsgMap);g_EventReadFileHandle = ::CreateEvent(NULL,TRUE,TRUE,NULL);g_EventReadFinishHandle = ::CreateEvent(NULL,TRUE,TRUE,NULL);//创建线程HANDLE hRFTHandle = CreateThread(NULL, 0, ReadFileThread, NULL, 0, &g_dwReadFileThreadID); HANDLE hWTHandle[MAX_WORKTHREAD];for (i=0; i<MAX_WORKTHREAD; i++){int* nTemp = new int;//如果不new,最后打印出来的WorkThread(LPVOID lpParam)的都是10//nTemp = &i;和*nTemp = i;区别。*nTemp = i;hWTHandle[i] = CreateThread(NULL, 0, WorkThread, nTemp, 0, &g_dwWorkThread[i]); WorkThreadCout ++;m_task[i] = 0;Sleep(100);}while (TRUE){if (nWorkFlag == 0){printf("输入要统计文件的路径或end退出\n");scanf("%s", g_workPath);DeleteMap();g_nTaskId = 0;nWorkTaslCount = 0;if (strcmp(g_workPath, "end") == 0){bReadFileFlag = FALSE;//读文件线程标志SetEvent(g_EventReadFileHandle);//读事件bRunFlag = FALSE;//让线程退出break;}SetEvent(g_EventReadFileHandle);//读事件nWorkFlag = 1;}ResetEvent(g_EventReadFinishHandle);WaitForSingleObject(g_EventReadFinishHandle, INFINITE);if (nReadFileFinish == 1){PrintMsg();}}Sleep(3000);DeleteMap();CloseHandle(hRFTHandle);for (i=0; i<MAX_WORKTHREAD; i++){CloseHandle(hWTHandle[i]);}CloseHandle(g_EventReadFileHandle); CloseHandle(g_EventReadFinishHandle); DeleteCriticalSection(&g_cs);DeleteCriticalSection(&g_MsgQueue);DeleteCriticalSection(&g_MsgMap);cout << "Main thread is end." << endl;cout << "#####代码行数统计测试结束#####" <<endl;//system("pause"); return 0; }int InitData(){return 0;}int DeleteMap(){std::map<int, T_CodeFileMsg*>::iterator IterFile;for(IterFile=m_FileMsgMap.begin(); IterFile!=m_FileMsgMap.end(); IterFile++){T_CodeFileMsg* file = (*IterFile).second;delete file;file = NULL;}m_FileMsgMap.clear();return 0;}DWORD WINAPI ReadFileThread(LPVOID lpParam) { // cout << "No." << g_dwThreadID << " thread is running." << endl; while (bRunFlag) { EnterCriticalSection(&g_cs);cout << "ReadFileThread " << g_dwReadFileThreadID << " thread is running." << endl;LeaveCriticalSection(&g_cs);ResetEvent(g_EventReadFileHandle);WaitForSingleObject(g_EventReadFileHandle, INFINITE);if (bReadFileFlag){int nTemp = DirectoryList(g_workPath);//nReadFileFinishnReadFileFinish = nTemp;if (nTemp == 1){PrintFile();nWorkFlag = 0;nTotalTaskCount = g_nTaskId;}else{nWorkFlag = 0;}SetEvent(g_EventReadFinishHandle);}Sleep(1000);} cout << "ReadFileThread " << g_dwReadFileThreadID << " end" << endl;return 0; } DWORD WINAPI WorkThread(LPVOID lpParam) { // cout << "No." << g_dwThreadID << " thread is running." << endl; int* nRemp = (int*)lpParam;while (bRunFlag) { int n = -1;T_CodeFileMsg* pCFMsg=NULL;EnterCriticalSection(&g_cs);//cout << "No " << *nRemp << ", " << g_dwWorkThread[*nRemp] << " thread is running." << endl;LeaveCriticalSection(&g_cs);EnterCriticalSection(&g_MsgQueue);if (!m_FileQueue.empty()){n = m_FileQueue.front();m_FileQueue.pop_front();if (nWorkTaslCount == 0){nTaskBeginTime = GetTickCount();}nWorkTaslCount++;m_task[*nRemp]++;}LeaveCriticalSection(&g_MsgQueue);EnterCriticalSection(&g_MsgMap);if ( n>= 0)//没有这个,在开始的时候n=-1会造成溢出。pCFMsg = m_FileMsgMap[n];LeaveCriticalSection(&g_MsgMap);EnterCriticalSection(&g_cs);//cout << "No:" << *nRemp << ", " << n << endl;if (pCFMsg!=NULL){cout << pCFMsg->FileName.c_str() << endl;}LeaveCriticalSection(&g_cs);if (pCFMsg!=NULL && n>=0){ProcessFile(pCFMsg, n);Sleep(20);}elseSleep(2000);} delete nRemp;nRemp = NULL;cout << "No " << lpParam << " end" << endl;return 0; }//根据文件类型处理int ProcessFile(T_CodeFileMsg* pTCFMsg, int n){EnterCriticalSection(&g_MsgMap);string tempFile = pTCFMsg->FileName;E_FILETYPE c_type = pTCFMsg->eFiletype;LeaveCriticalSection(&g_MsgMap);switch(c_type){case E_C:ProcessCFile(pTCFMsg, tempFile.c_str(), n);break;case E_JAVA:ProcessJavaFile(pTCFMsg, tempFile.c_str(), n);break;default:break;}return 0;}int ProcessCFile(T_CodeFileMsg* pTCFMsg, char* strFile, int n){ifstream in;char buf[MAX_CHAR] = {0};bool bNoteFlag = FALSE;int nNoteLine = 0;int nEmptyLine = 0;int nCodeLine = 0;int nTotalLine = 0;in.open(strFile);while(in.getline(buf, sizeof(buf))) {nTotalLine++;char* p = buf; while((*p ==' ' || *p=='\t')) p++;if (!bNoteFlag){if (*p == 0){nEmptyLine++;cout << nTotalLine <<endl;}else if (strncmp(p, "/*", 2)==0) {char* q = buf+strlen(buf)-1;while((*q ==' ' || *q=='\t')) q--;q--;//判断是不是/*AAA*/if (strncmp(q, "*/", 2)==0){}elsebNoteFlag = TRUE;nNoteLine++;cout << nTotalLine <<endl;}else if (strncmp(p, "//", 2)==0) {nNoteLine++;cout << nTotalLine <<endl;}else{nCodeLine++;}}else{if (*p == 0){nNoteLine++;cout << nTotalLine <<endl;}else if (strncmp(p, "*/", 2)==0) {bNoteFlag = FALSE;nNoteLine++;cout << nTotalLine <<endl;}else {nNoteLine++;cout << nTotalLine <<endl;char* q = buf+strlen(buf)-1;while((*q ==' ' || *q=='\t')) q--;q--;if (strncmp(q, "*/", 2)==0){bNoteFlag = FALSE;}}}memset(buf, 0, MAX_CHAR);}EnterCriticalSection(&g_MsgMap);pTCFMsg->nCodeLine = nCodeLine;pTCFMsg->nEmptyLine = nEmptyLine;pTCFMsg->nNoteLine = nNoteLine;pTCFMsg->nTotalLine = nTotalLine;m_FileMsgMap[n] = pTCFMsg;LeaveCriticalSection(&g_MsgMap);return 0;}int ProcessJavaFile(T_CodeFileMsg* pTCFMsg, char* strFile, int n){return 0;}int AddFile2Map(char* pFile){string strFile = strlwr(pFile);int nRet = strFile.find(".", 0);if (nRet>0){string Temp;int nLen = strFile.size();Temp = strFile.substr(nRet, strFile.size()-nRet);if (strcmp(Temp.c_str(),".c")==0 || strcmp(Temp.c_str(),".cpp")==0 || strcmp(Temp.c_str(),".h")==0){T_CodeFileMsg* pTemp = new T_CodeFileMsg;m_FileMsgMap[g_nTaskId] = pTemp;//m_FileMsgMap[g_nTaskId] = new T_CodeFileMsg;//T_CodeFileMsg* pTemp = m_FileMsgMap[g_nTaskId];pTemp->eFiletype = E_C;pTemp->nTaskId = g_nTaskId;pTemp->FileName = pFile;//pTemp->FileName = new char[nLen+1];//memcpy(pTemp->FileName, strFile.c_str(), nLen);//m_FileMsgMap[g_nTaskId] = pTemp;//m_FileMsgMap.insert(pair <int, T_CodeFileMsg* >(g_nTaskId, pTemp));m_FileQueue.push_back(g_nTaskId);g_nTaskId++;}}return 0;}int DirectoryList(LPCSTR Path){WIN32_FIND_DATA FindData;HANDLE hError;int FileCount = 0;char FilePathName[MAX_LEN];// 构造路径char FullPathName[MAX_LEN];strcpy(FilePathName, Path);strcat(FilePathName, "\\*.*");hError = FindFirstFile(FilePathName, &FindData);if (hError == INVALID_HANDLE_VALUE){printf("搜索失败!\n");return 0;}while(::FindNextFile(hError, &FindData)){// 过虑.和..if (strcmp(FindData.cFileName, ".") == 0|| strcmp(FindData.cFileName, "..") == 0 ){continue;}// 构造完整路径wsprintf(FullPathName, "%s\\%s", Path,FindData.cFileName);FileCount++;AddFile2Map(FullPathName);// 输出本级的文件//printf("\n%d %s ", FileCount, FullPathName);if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){//printf("<Dir>");DirectoryList(FullPathName);}}return 1;}int PrintFile(){EnterCriticalSection(&g_MsgMap);std::map<int, T_CodeFileMsg*>::iterator IterFile;for(IterFile=m_FileMsgMap.begin(); IterFile!=m_FileMsgMap.end(); IterFile++){T_CodeFileMsg* file = (*IterFile).second;//EnterCriticalSection(&g_cs);cout << endl;cout << file->FileName.c_str();cout << ", id:" << file->nTaskId;cout << ", nCodeLine:"<< file->nCodeLine;cout << ", nEmptyLine:"<< file->nEmptyLine;cout << ", nNoteLine:"<< file->nNoteLine;cout << ", nTotalLine:"<< file->nTotalLine;//LeaveCriticalSection(&g_cs);}LeaveCriticalSection(&g_MsgMap);return 0;}int PrintMsg(){while (TRUE){if (nWorkTaslCount == nTotalTaskCount){std::map<int, int>::iterator IterCount;for(IterCount=m_task.begin(); IterCount!=m_task.end();IterCount++){int nThreadId= (*IterCount).first;int nCount = (*IterCount).second;EnterCriticalSection(&g_cs);cout << "nThreadId:" << nThreadId << ", nCount:" << nCount<<endl;LeaveCriticalSection(&g_cs);(*IterCount).second = 0;}nWorkFlag = 0;PrintFile();break;}cout << "nWorkTaslCount:" << nWorkTaslCount << ", nTotalTaskCount:" << nTotalTaskCount <<endl;Sleep(1000);}return 0;}有兴趣的朋友可以自己试试,仅供参考。
转载请注明原创链接:http://blog.csdn.net/wujunokay/article/details/12586589