测试数据数量1300W.测试加载时间110秒-150秒。
测试查找速度,越靠前越快。最后一条数据耗时6-8秒
#include <iostream> #include <io.h> #include <map> #include <thread> #include <unistd.h> #include <pthread.h> #include <clocale> #include <vector> using namespace std; //线程锁 static pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; //数据存储的,key为邮箱,value为行号 multimap<string,int>*datas=new multimap<string,int>; //数据存储2,key为行号,value为行内容长度 map<int,int>*dataHnums=new map<int,int>; int tcnt=0; FILE* fp; bool flag=false; int cnt=-1; void loadDataMap() { char row[1024]; char *tmp=row; int hnum=0; string data; int idx=0; int len=0; int ocnt=0; vector<pair<string,int> >tmpdatas; vector<pair<int,int> >tmphnums; bool isend=false; while(!isend) { // cout<<1<<endl; //加锁 pthread_mutex_lock(&mutex); if(fgets(row,1024,fp)==NULL) { //cout<<"数据读取完成,退出线程"<<endl; isend=true; } //如果还未结束 if(!isend) { cnt++; ocnt=cnt; } pthread_mutex_unlock(&mutex); if(!isend) { data=row; len=data.length(); idx=data.find(','); row[idx]=NULL; //尽量将插入操作放在锁外部进行,数据插入临时的栈空间 tmpdatas.push_back(pair<string,int>(row,ocnt)); tmphnums.push_back(pair<int,int>(ocnt,len)); } if(ocnt!=0&&ocnt%100000==0) { cout<<ocnt<<endl; //每读取到10W数据。则将栈空间的数据填充到堆空间一次 pthread_mutex_lock(&mutex); datas->insert(tmpdatas.begin(),tmpdatas.end()); dataHnums->insert(tmphnums.begin(),tmphnums.end()); tmpdatas.clear(); dataHnums->clear(); pthread_mutex_unlock(&mutex); } } //将剩下的数据填充到堆空间 pthread_mutex_lock(&mutex); datas->insert(tmpdatas.begin(),tmpdatas.end()); dataHnums->insert(tmphnums.begin(),tmphnums.end()); tmpdatas.clear(); tmphnums.clear(); tcnt--; if(tcnt<=0) { flag=true; } pthread_mutex_unlock(&mutex); } //加载数据 void init() { fp=fopen("dangdangwang.txt","r"); if(fp==NULL) { cout<<"未找到数据文件"; return; } clockid_t start=clock(); //开启30条线程加载数据 for(int i=0;i<30;i++) { tcnt++; thread th(loadDataMap); th.detach(); } //等待子线程 while(!flag) { sleep(1); } clockid_t end=clock(); int z=0; cout<<"数据初始化完成:"<<datas->size()<<"耗时:"<<((double)(end-start))/CLOCKS_PER_SEC<<"秒"<<endl; fclose(fp); } //根据条件打印n条数据 void loadDataTop(int n) { FILE* fp=fopen("dangdangwang.txt","r"); if(fp==NULL) { cout<<"未找到数据文件"; return; } char row[1024]; cout<<"********************************"<<endl; for(int i=0;i<n;i++) { if(fgets(row,1024,fp)!=NULL) { cout<<row<<endl; } } cout<<"********************************"<<endl; fclose(fp); } //根据行号取数据 void loadDataByHnum(int n) { FILE* fp=fopen("dangdangwang.txt","r"); if(fp==NULL) { cout<<"未找到数据文件"; return; } int h=0; //计算出文件指针跳转的位置 for(int i=0;i<n;i++) { if(dataHnums->count(i)>0) { h+=(*dataHnums)[i]+1; } else { break; } } //跳转指针直接读取一行 fseek(fp,h,SEEK_SET); char row[1024]; fgets(row,1024,fp); cout<<row<<endl; fclose(fp); } int main() { init(); while(true) { cout << "请选择需要进行的操作:1、展示前若干条数据,2、根据指定邮箱搜索数据" << endl; int num; cin>>num; getchar(); if(num==1) { cout<<"请输入要展示的行数:"; cin>>num; getchar(); loadDataTop(num); } else if(num==2) { cout<<"请输入要查询的邮箱:"; char mail[25]; cin.getline(mail,25); if(datas->count(mail)<=0) { cout<<"未查询到该邮箱"<<endl; } else { auto itr=(*datas).find(mail); loadDataByHnum((*itr).second); } } else cout<<"输入了错误的选项:"<<num<<",请重新输入!"<<endl; } return 0; }