现在的位置: 首页 > 综合 > 正文

多线程执行顺序

2013年10月04日 ⁄ 综合 ⁄ 共 3339字 ⁄ 字号 评论关闭

 

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

首先在每次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);

}

就不能保证线程执行的顺序了,但两种方法都可确定所有线程执行完毕

 

抱歉!评论已关闭.