在做一个爬天气网上的多个省的天气网页,感觉单线程太慢,随用到多线程看看能优化多少。。。
首先在每次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); 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);
}
就不能保证线程执行的顺序了,但两种方法都可确定所有线程执行完毕