前言
以一个面试题为例子:
- 读取data.txt文件内容
- 使用多线程处理
- 使用宏定义线程数量
第一版实现:(面试时写得答案是这个类似)
#include <stdio.h> #include <stdlib.h> #include <vector> #include <iostream> #include <memory> #include <thread> #include <mutex> #define MAX_SIZE 200*1024 #define MAX_THREAD_COUNT 10 int main() { FILE* pFile = fopen("D:\\workspace\\vs2015\\Project1\\Debug\\data.txt","rb"); if (!pFile) { printf("file open error \n"); return -1; } char szBuff[MAX_SIZE] = { 0 }; int i = 0; while (!feof(pFile)) { fread(&szBuff[i * 1024], 1, 1024, pFile); i++; } fclose(pFile); char szDoubleValue[8] = {0}; int nDoubleValueIndex = 0; std::vector<double> vectDoubleList; for (size_t i = 0; i < strlen(szBuff); i++) { if (szBuff[i] == '\r') { float fValue = atof(szDoubleValue); vectDoubleList.push_back(fValue); //printf("%f\n", fValue); continue; } if (szBuff[i] == '\n') { nDoubleValueIndex = 0; memset(szDoubleValue, 0, 8); continue; } szDoubleValue[nDoubleValueIndex] = szBuff[i]; nDoubleValueIndex++; } if (vectDoubleList.size() <= 0) { printf("vectDoubleList empty \n"); return -1; } std::unique_ptr<std::thread> thThreadPtrList[MAX_THREAD_COUNT - 1]; volatile int nHasProIndex = 0; double dTotalValue = 0; int size = vectDoubleList.size(); std::mutex lock; long lStartTime = clock(); for (size_t i = 0; i < MAX_THREAD_COUNT - 1; i++) { thThreadPtrList[i] = std::unique_ptr<std::thread>( new std::thread([&]() { while(1) { std::lock_guard<std::mutex> locker(lock); if (nHasProIndex != size) { dTotalValue += vectDoubleList[nHasProIndex]; nHasProIndex++; } else { break; } } }) ); } while (1) { std::lock_guard<std::mutex> locker(lock); if (nHasProIndex != size) { dTotalValue += vectDoubleList[nHasProIndex]; nHasProIndex++; } else { break; } } long lEndTime = clock(); double dAvarageValue = dTotalValue / vectDoubleList.size(); printf("Total Count:%d \nMedium Value:%f \nAvarage Value:%f \n", vectDoubleList.size(),vectDoubleList[vectDoubleList.size()/2], dAvarageValue); printf("Total Time:%d \n", lEndTime - lStartTime); for (size_t i = 0; i < MAX_THREAD_COUNT -1; i++) { thThreadPtrList[i]->join(); } system("pause"); return 0; }
面试的大佬 给提了几个建议:
- 尽量不要用锁 (用户态转为内核态需要一些开销)
- 尽量不要裸指针,裸指针容易忘记销毁 异常捕获会被上层捕获 内存泄漏。
同时申明一点智能指针具有传递性,函数的形参也需要是智能指针。
- 尽量使用c++读取文件,虽然c原生比c++流 速度快。
- 尽量不要使用全局变量
- 主线程也要用上,这算小技巧
- 线程算法能优化,可以使用Google的map-reduces算法,类似根据线程数量把数据进行分段处理。
当时在ubuntu上编程的,很懵逼,线程库用不了,需要qt pro文件 添加 LIBS += pthread.lib