多线程执行顺序

来源:互联网 发布:手机淘宝开店我是卖家 编辑:程序博客网 时间:2024/05/21 06:23

在做一个爬天气网上的多个省的天气网页,感觉单线程太慢,随用到多线程看看能优化多少。。。

首先在每次CreateThread后Sleep(1000),总共建32个线程,每个线程对应一个网页:

[cpp] view plaincopy
  1. for(int i=0;i<32;i++)  
  2. {  
  3. hThread[i]=CreateThread(NULL,0,WeatherProc,p,0,&dwThreadId[i]);  
[cpp] view plaincopy
  1. Sleep(1000);      
  2. }  

这样会快点,但是想到一个问题,如果抓取的HTML文件还没有存储完毕,主线程就结束,在这里说一下,不管你创建的线程运行到哪,主线程不管,只要main()里的语句执行完,所有线程也就结束了。这样的话整个程序就没有什么意义。。。存取的数据不完整。

Sleep(1000)试了下会存在该种情况,换了Sleep(2000),存储完整了,但是感觉这个不是完美的解决方案。Sleep(2000)确实让线程抢占的机会多了,但是还是不能确保完整存储所有网页的信息。

后来想到一个方法就是设置标志量法了

[cpp] view plaincopy
  1. while(1)  
  2. {  
  3.   
  4. for( i=0;i<32;i++)  
  5. {  
  6.     if(flag[i]==0)  
  7.     {  
  8.         Sleep(100);  
  9.     i=-1;  
  10.     }  
  11.   
  12. }  
  13. if(i==32)  
  14.     break;  
  15. }  


 

在每个线程的执行函数末尾将flag数组的对应位置设置为1,表明该网页已经完整存储。只要存在任何一个网页没有存储完毕,主线程睡觉。。。。

线程这东西运用的好的话,的确很有用,但是搞不清的话,结果让人很苦恼。

已经从最初单线程十分钟减小到5秒。

linux下可以这样,让线程必须执行:

[cpp] view plaincopy
  1.  #include<stdio.h>  
  2. #include<unistd.h>  
  3. #include<pthread.h>  
  4. void* task(void* x)  
  5. {  
  6. int i;  
  7. for(i=0;i<10000;i++)  
  8. printf("task is running\n");  
  9. pthread_exit((void*)0);  
  10.   
  11. }  
  12. int main()  
  13. {  
  14. int ret=0;  
  15. void *p;  
  16. pthread_t pid;  
  17. pthread_attr_t attr;  
  18. pthread_attr_init(&attr);  
  19. pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);//如果第三个参数设置为PTHREAD_CRAETE_DETACHED,那就不能确定线程是否会执行  
  20. pthread_create(&pid,&attr,task,NULL);  
  21. ret=pthread_join(pid,&p);  
  22. printf("ret=%d,p=%d\n",ret,(int)p);  
  23. //sleep(3);  
  24.   
  25. }  

现在有C++11已经支持join这种形式了,但好多还不支持。。。

[cpp] view plaincopy
  1. void my_thread()  
  2. {  
  3.     puts("hello, world");  
  4. }  
  5.   
  6. int main(int argc, char *argv[])  
  7. {  
  8.     std::thread t(my_thread);  
  9.     t.join();  
  10.   
  11.     system("pause");  
  12.     return 0;  
  13. }  


 

[cpp] view plaincopy
  1. #include <iostream>  
  2. #include <stdlib.h>  
  3. #include <thread>  
  4. #include <string>  
  5.   
  6. void my_thread(int num, const std::string& str)  
  7. {  
  8.     std::cout << "num:" << num << ",name:" << str << std::endl;  
  9. }  
  10.   
  11. int main(int argc, char *argv[])  
  12. {  
  13.     int num = 1234;  
  14.     std::string str = "tujiaw";  
  15.     std::thread t(my_thread, num, str);//传参很方便了  
  16.     t.detach();//设置为分离  
  17.       
  18.     system("pause");  
  19.     return 0;  
  20. }  

独占式互斥量:

[cpp] view plaincopy
  1. #include <iostream>  
  2. #include <stdlib.h>  
  3. #include <thread>  
  4. #include <string>  
  5. #include <mutex>  
  6.   
  7. int g_num = 0;  
  8. std::mutex g_mutex;  
  9.   
  10. void thread1()  
  11. {  
  12.     //g_mutex.lock();  
  13. std::lock_guard<std::mutex> lg(g_mutex); <span>  </span>   g_num = 10;  
  14.     for (int i=0; i<10; i++){  
  15.         std::cout << "thread1:" << g_num << std::endl;  
  16.     }  
  17.     //g_mutex.unlock();  
  18. }  
  19.   
  20. void thread2()  
  21. {  
  22.     std::lock_guard<std::mutex> lg(g_mutex);  
  23.     g_num = 20;  
  24.     for (int i=0; i<10; i++){  
  25.         std::cout << "thread2:" << g_num << std::endl;  
  26.     }  
  27. }  
  28.   
  29. int main(int argc, char *argv[])  
  30. {  
  31.     std::thread t1(thread1);  
  32.     std::thread t2(thread2);  
  33.     t1.join();  
  34.     t2.join();  
  35.       
  36.     system("pause");  
  37.     return 0;  
  38. }  


允许超时的互斥量

[cpp] view plaincopy
  1. std::timed_mutex g_timed_mutex;  
  2. void thread1()  
  3. {  
  4.     std::unique_lock<std::timed_mutex> tl(g_timed_mutex);  
  5.     ::Sleep(3000); // 睡眠3秒  
  6.     puts("thread1");  
  7. }  
  8.   
  9. void thread2()  
  10. {  
  11.     std::unique_lock<std::timed_mutex> tl(g_timed_mutex, std::chrono::milliseconds(1000)); // 超时时间1秒  
  12.     puts("thread2");  
  13. }  
  14.   
  15. int main(int argc, char *argv[])  
  16. {  
  17.     std::thread t1(thread1);  
  18.     ::Sleep(100); // 让线程1先启动  
  19.     std::thread t2(thread2);  
  20.     t1.join();  
  21.     t2.join();  
  22.       
  23.     system("pause");  
  24.     return 0;  
  25. }  


C++11不支持的话只有这样了:

[cpp] view plaincopy
  1. #include<windows.h>  
  2. #include<stdio.h>  
  3. #include<string.h>  
  4. #include <stdlib.h>  
  5. HANDLE h[10];  
  6. DWORD WINAPI x(LPVOID pParam)  
  7. {  
  8.     if(pParam)  
  9.     {  
  10.         int i=*(int *)pParam;  
  11.         for(int j=0;j<10;j++)  
  12.             printf("%d\n",i);     
  13.     }  
  14.     return 1;  
  15. }  
  16. int main()  
  17. {  
  18.     int i;  
  19.     for(i=0;i<10;i++)    
  20.     {  
  21.         int *p=new int ;  
  22.         *p=i;  
  23.         h[i]=CreateThread(NULL,0,x,(void *)p,0,NULL);    
  24.   
  25.         ::WaitForSingleObject(h[i],INFINITE);  
  26.     }  
  27.     //for(i=0;i<10;i++)    
  28.     //::WaitForSingleObject(h[i],INFINITE);  
  29.   
  30. }  


这样可以确定线程执行的顺序,也就是说线程1执行完了后线程2再执行。。。。。

如果这样:

[cpp] view plaincopy
  1. #include<windows.h>  
  2. #include<stdio.h>  
  3. #include<string.h>  
  4. #include <stdlib.h>  
  5. HANDLE h[10];  
  6. DWORD WINAPI x(LPVOID pParam)  
  7. {  
  8.     if(pParam)  
  9.     {  
  10.         int i=*(int *)pParam;  
  11.         for(int j=0;j<10;j++)  
  12.             printf("%d\n",i);     
  13.     }  
  14.     return 1;  
  15. }  
  16. int main()  
  17. {  
  18.     int i;  
  19.     for(i=0;i<10;i++)    
  20.     {  
  21.         int *p=new int ;  
  22.         *p=i;  
  23.         h[i]=CreateThread(NULL,0,x,(void *)p,0,NULL);    
  24.   
  25.         //::WaitForSingleObject(h[i],INFINITE);  
  26.     }  
  27.     for(i=0;i<10;i++)    
  28.     ::WaitForSingleObject(h[i],INFINITE);  
  29.   
  30. }  

就不能保证线程执行的顺序了,但两种方法都可确定所有线程执行完毕
0 0
原创粉丝点击