在做一個爬天氣網上的多個省的天氣網頁,感覺單線程太慢,隨用到多線程看看能優化多少。。。
首先在每次CreateThread後Sleep(1000),總共建32個線程,每個線程對應一個網頁:
- for(int i=0;i<32;i++)
- {
- hThread[i]=CreateThread(NULL,0,WeatherProc,p,0,&dwThreadId[i]);
- Sleep(1000);
- }
這樣會快點,但是想到一個問題,如果抓取的HTML文件還沒有存儲完畢,主線程就結束,在這裏說一下,不管你創建的線程運行到哪,主線程不管,只要main()裏的語句執行完,所有線程也就結束了。這樣的話整個程序就沒有什麼意義。。。存取的數據不完整。
Sleep(1000)試了下會存在該種情況,換了Sleep(2000),存儲完整了,但是感覺這個不是完美的解決方案。Sleep(2000)確實讓線程搶佔的機會多了,但是還是不能確保完整存儲所有網頁的信息。
後來想到一個方法就是設置標誌量法了
- while(1)
- {
- for( i=0;i<32;i++)
- {
- if(flag[i]==0)
- {
- Sleep(100);
- i=-1;
- }
- }
- if(i==32)
- break;
- }
在每個線程的執行函數末尾將flag數組的對應位置設置爲1,表明該網頁已經完整存儲。只要存在任何一個網頁沒有存儲完畢,主線程睡覺。。。。
線程這東西運用的好的話,的確很有用,但是搞不清的話,結果讓人很苦惱。
已經從最初單線程十分鐘減小到5秒。
linux下可以這樣,讓線程必須執行:
- #include<stdio.h>
- #include<unistd.h>
- #include<pthread.h>
- void* task(void* x)
- {
- int i;
- for(i=0;i<10000;i++)
- printf("task is running\n");
- pthread_exit((void*)0);
- }
- int main()
- {
- int ret=0;
- void *p;
- pthread_t pid;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);//如果第三個參數設置爲PTHREAD_CRAETE_DETACHED,那就不能確定線程是否會執行
- pthread_create(&pid,&attr,task,NULL);
- ret=pthread_join(pid,&p);
- printf("ret=%d,p=%d\n",ret,(int)p);
- //sleep(3);
- }
現在有C++11已經支持join這種形式了,但好多還不支持。。。
- void my_thread()
- {
- puts("hello, world");
- }
- int main(int argc, char *argv[])
- {
- std::thread t(my_thread);
- t.join();
- system("pause");
- return 0;
- }
- #include <iostream>
- #include <stdlib.h>
- #include <thread>
- #include <string>
- void my_thread(int num, const std::string& str)
- {
- std::cout << "num:" << num << ",name:" << str << std::endl;
- }
- int main(int argc, char *argv[])
- {
- int num = 1234;
- std::string str = "tujiaw";
- std::thread t(my_thread, num, str);//傳參很方便了
- t.detach();//設置爲分離
- system("pause");
- return 0;
- }
獨佔式互斥量:
- #include <iostream>
- #include <stdlib.h>
- #include <thread>
- #include <string>
- #include <mutex>
- int g_num = 0;
- std::mutex g_mutex;
- void thread1()
- {
- //g_mutex.lock();
- std::lock_guard<std::mutex> lg(g_mutex); <span> </span> g_num = 10;
- for (int i=0; i<10; i++){
- std::cout << "thread1:" << g_num << std::endl;
- }
- //g_mutex.unlock();
- }
- void thread2()
- {
- std::lock_guard<std::mutex> lg(g_mutex);
- g_num = 20;
- for (int i=0; i<10; i++){
- std::cout << "thread2:" << g_num << std::endl;
- }
- }
- int main(int argc, char *argv[])
- {
- std::thread t1(thread1);
- std::thread t2(thread2);
- t1.join();
- t2.join();
- system("pause");
- return 0;
- }
允許超時的互斥量
- std::timed_mutex g_timed_mutex;
- void thread1()
- {
- std::unique_lock<std::timed_mutex> tl(g_timed_mutex);
- ::Sleep(3000); // 睡眠3秒
- puts("thread1");
- }
- void thread2()
- {
- std::unique_lock<std::timed_mutex> tl(g_timed_mutex, std::chrono::milliseconds(1000)); // 超時時間1秒
- puts("thread2");
- }
- int main(int argc, char *argv[])
- {
- std::thread t1(thread1);
- ::Sleep(100); // 讓線程1先啓動
- std::thread t2(thread2);
- t1.join();
- t2.join();
- system("pause");
- return 0;
- }
C++11不支持的話只有這樣了:
- #include<windows.h>
- #include<stdio.h>
- #include<string.h>
- #include <stdlib.h>
- HANDLE h[10];
- DWORD WINAPI x(LPVOID pParam)
- {
- if(pParam)
- {
- int i=*(int *)pParam;
- for(int j=0;j<10;j++)
- printf("%d\n",i);
- }
- return 1;
- }
- int main()
- {
- int i;
- for(i=0;i<10;i++)
- {
- int *p=new int ;
- *p=i;
- h[i]=CreateThread(NULL,0,x,(void *)p,0,NULL);
- ::WaitForSingleObject(h[i],INFINITE);
- }
- //for(i=0;i<10;i++)
- //::WaitForSingleObject(h[i],INFINITE);
- }
這樣可以確定線程執行的順序,也就是說線程1執行完了後線程2再執行。。。。。
如果這樣:
- #include<windows.h>
- #include<stdio.h>
- #include<string.h>
- #include <stdlib.h>
- HANDLE h[10];
- DWORD WINAPI x(LPVOID pParam)
- {
- if(pParam)
- {
- int i=*(int *)pParam;
- for(int j=0;j<10;j++)
- printf("%d\n",i);
- }
- return 1;
- }
- int main()
- {
- int i;
- for(i=0;i<10;i++)
- {
- int *p=new int ;
- *p=i;
- h[i]=CreateThread(NULL,0,x,(void *)p,0,NULL);
- //::WaitForSingleObject(h[i],INFINITE);
- }
- for(i=0;i<10;i++)
- ::WaitForSingleObject(h[i],INFINITE);
- }
就不能保證線程執行的順序了,但兩種方法都可確定所有線程執行完畢