多線程執行順序

在做一個爬天氣網上的多個省的天氣網頁,感覺單線程太慢,隨用到多線程看看能優化多少。。。

首先在每次CreateThread後Sleep(1000),總共建32個線程,每個線程對應一個網頁:

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

這樣會快點,但是想到一個問題,如果抓取的HTML文件還沒有存儲完畢,主線程就結束,在這裏說一下,不管你創建的線程運行到哪,主線程不管,只要main()裏的語句執行完,所有線程也就結束了。這樣的話整個程序就沒有什麼意義。。。存取的數據不完整。

Sleep(1000)試了下會存在該種情況,換了Sleep(2000),存儲完整了,但是感覺這個不是完美的解決方案。Sleep(2000)確實讓線程搶佔的機會多了,但是還是不能確保完整存儲所有網頁的信息。

後來想到一個方法就是設置標誌量法了

  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下可以這樣,讓線程必須執行:

  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這種形式了,但好多還不支持。。。

  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. }  


 

  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. }  

獨佔式互斥量:

  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. }  


允許超時的互斥量

  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不支持的話只有這樣了:

  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再執行。。。。。

如果這樣:

  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. }  

就不能保證線程執行的順序了,但兩種方法都可確定所有線程執行完畢
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章