Chinaunix首页 | 论坛 | 博客
  • 博客访问: 455112
  • 博文数量: 724
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5010
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:47
文章分类

全部博文(724)

文章存档

2011年(1)

2008年(723)

我的朋友

分类:

2008-10-13 16:56:37

如何让程序自动管理线程
作者:



引言
多线程是一种很好的程序机制,使用线程可以充分的利用电脑资源,进行并行的业务处理。不过好的东西总有它的不足。线程是好,不过滥用,或管理不当就会造成线程混乱,内存漏洞,造成电脑速度变慢,反应迟钝。

想法
于是有人提出能不能让线程自己管理自己,把这复杂的工作交给电脑来处理。笔者经过多年的实践,终于用VC++实现了这一目的。
大家知道在VC++中我们可以用CreateThread创建一个线程,该函数返回这线程的Handle,以后我们就可以用这个Handle来管理这个线程的。于是我们可以做一个类名为ThreadManager,来管理这些Handle,并随时监控这些线程的状态。
总的思想就是这样,不过为了方便使用,我们最好把这个类封装成DLL的形式,这样以后我们在任何程序中都可以很方便的用该类来管理线程了(当然如果你有兴趣,也可以用COM模型来实现)。

实现
因为我们要把一切工作全交给ThreadManager,所以线程的创建,监控,删除都将在该类中实现,而我们仅要做的就是把线程函数名和线程参数传给ThreadManager类,于是我们定义该类构造函数为:

ThreadManager(ThreadPrc threadpro,LPVOID pParam);
该类还要能启动线程,于是我们又定义一个启动函数:
RunThread();
另外我们有时还要能获得线程的Handle,于是又定义一个函数:
HANDLE GetThreadHandle();
而该类唯一的成员参数就是Handle:
HANDLE m_Handle;
于是ThreadManager定义如下:
typedef DWORD (WINAPI *ThreadPro)(LPVOID);
class  CThreadManager : public CObject
{
	DECLARE_DYNAMIC( CThreadManager ) 
public:
	CThreadManager( ThreadPrc threadpro, LPVOID pParam);
	~CThreadManager();
	CBOOL RunThread();
	HANDLE GetThreadHandle() const { return( m_Handle ); };  
private:
	HANDLE m_Handle;
};
显然,我们仅有这一个类还不能完成我们所需的工作,我们还要一个负责具体监控的ThreadTask类,ThreadTask类中有一个监控线程ThreadTaskFunc( )负责监控并删除线程。该类定义如下:
class CThreadTask : public CObject
{
DECLARE_DYNAMIC( CThreadTask )
public:
	CThreadTask();  //构造函数
	~CThreadTask();
	CBOOL IsValid();  
	void AddHandle( CONST HANDLE cHandle );  //添加线程句柄到m_ObList中
	 
	void CloseThreadHandles();    //(关闭线程)
	static CThreadTask& GetCThreadTask();    //用于在Managerthread类中获得ThreadTask类的指针

	CObList	m_ObList;//线程句柄组
	HANDLE m_Handle;//线程句柄
	 
	BOOL m_bKeepGoing;//是否已运行
};

IMPLEMENT_DYNAMIC( CThreadCareTaker, CObject )
其中IsValid()是用于检验ThreadTaskFunc()是否已动行了,其它意思都很明显。

流程图
总的流程图如下:


具体实现
下面给出它的具体实现。

ThreadTask::ThreadTask()
{
  m_bKeepGoing = TRUE;
  //表示已运行
  DWORD nThreadId = 0;
  //创建管理线程
  m_Handle = (HANDLE)::CreateThread(NULL,0,ThreadTaskpro,0,0,&nThreadId );
}
void ThreadTask::AddHandle( CONST HANDLE cHandle )
{
	CHandle *pHandle = new CHandle;
	pHandle->m_ThreadHandle = cHandle;
	m_ObList.AddTail( pHandle );
	 
}
void ThreadTask::CloseThreadHandles()
{
	if ( m_ObList.GetCount() )
	{
		POSITION pos1, pos2;
		CHandle *pHandle = (CHandle *)NULL;  
		//(CHandle类相当简单,只有一个成员函数m_ThreadHandle)
		DWORD dwExitCode = 0L;
		for( pos1=m_ObList.GetHeadPosition(); (pos2=pos1)!=POSITION(NULL); )
		{
			//历遍所有已有的线程句柄
			pHandle = DYNAMIC_DOWNCAST( CHandle, m_ObList.GetNext( pos1 ) );
			//获得第pos1个handle
			VERIFY( ::GetExitCodeThread( pHandle->m_ThreadHandle, &dwExitCode ) );
			//获得线程pHandle的当前状态
			if ( dwExitCode != STILL_ACTIVE )
			//如果已完成
			{
				//释放当前句柄
				m_ObList.RemoveAt( pos2 );	 
		 
				VERIFY( ::CloseHandle( pHandle->m_ThreadHandle ) );
				delete pHandle;
				pHandle = (CHandle *)NULL;
			}
		}
	}
}

ThreadTask::~ThreadTask()
{

}

ThreadTask & ThreadTask::GetThreadTask()
{
	//返回静态ThreadTask对象,以便ThreadManager类调用
	static ThreadTask  Taker;
	return(Taker);
}

BOOL ThreadTask::IsValid()
{
	//是否已运行
	BOOL bValid_Status = FALSE;
	if ( (this != NULL) && AfxIsValidAddress( this, sizeof( ThreadTask ) ) )
		bValid_Status = TRUE;
	return( bValid_Status );
}
下面介绍线程ThreadTaskpro(); 该线程最主要的目的就是调用ThreadTask的CloseThreadHandles()函数,实现如下:
DWORD WINAPI ThreadTaskpro( LPVOID pParam  )
{
 
	HANDLE hCurrentThread = GetCurrentThread();
	//获得该线程句柄
	SetThreadPriority( hCurrentThread, THREAD_PRIORITY_LOWEST );
	//设为最低
	while ( ThreadTask::GetThreadTask().m_bKeepGoing )

	{
    Sleep(500);
	//休息500mms
 
		ThreadTask::GetThreadTask().CloseThreadHandles();
	}
 
	SetThreadPriority( hCurrentThread, THREAD_PRIORITY_NORMAL );
	return( 0 );
}
ThreadTask类到这就介绍完了,下面我们看看ThreadManager类的实现,其实它的工作已很小,就是启动要管理的线程(在构造函数中完成),并控制ThreadTask类。 具体实现:
ThreadManager::ThreadManager(ThreadPro threadpro,  LPVOID pParam)
{

	DWORD nThreadId = 0;
	 _ASSERTE( ThreadTask::GetThreadTask().IsValid() );
	//运行ThreadTask类

	m_Handle = (HANDLE)::CreateThread(NULL,0,threadpro,(LPVOID)pParam,0,&nThreadId );
	//创建要管理的线程,并返回句柄
	if ( ThreadTask::GetThreadTask().m_bKeepGoing )
	{
		//如果ThreadTask运行了的话 
		ASSERT( m_Handle );
		ThreadTask::GetThreadTask().AddHandle( m_Handle );
		//把句柄加入ThreadTask类中,以便管理
	} 
}

ThreadManager::~ThreadManager()
{

}

BOOL  ThreadManager::RunThread()
{
	//运行线程
	return( ::ResumeThread( m_Handle ) != 0xFFFFFFFF );
}
整在机制就介绍完了。

使用方法

使用方法相当简单,比如说,我要运行进程MyThread1,并传入参数m_pro,只要用以下代码就可以了:
 ThreadManager ThreadManager( &MyThread1, (LPVOID)m_pro );
 	ThreadManager.RunThread();
就可以了,用这种方法创的线程,会自动由ThreadManager类管理,并在完成的工作时,自动释放线程资源。 我做了一个示例,大家可以试着运行一下。

作者信息:
姓名:赵明
email: papaya_zm@sina.com 或 zmpapaya@hotmail.com
主页:
--------------------next---------------------

不错了!
这位老兄已经把关于多线程框子讲的很明白了,至于那个所谓的自动管理,只过是见仁见智置罢了,究竟做到哪一步才算完整和完美呢?!
我个人认为他这块砖抛得可以了,至于那些引出来玉能否经得起一试?不如就看今朝吧! ( longtaixu 发表于 2003-12-22 10:13:00)
 
我也不明白所谓的“系统自动管理”是什么意思?!
照你程序看,仅仅是为了线程退出之后关闭线程句柄用
的。那么如果线程在运行期间申请了Memory,虽然退出
了,但是没有释放,你的程序能发现么?能“自动”
处理么?那如果线程死循环了呢?
( jeff_huazhou 发表于 2003-12-5 13:31:00)
 
看看这个
( xiaotaoliang 发表于 2002-12-30 16:30:00)
 
不如参考一下java的线程类。 ( xiaotaoliang 发表于 2002-12-30 15:49:00)
 
可以,继续努力 ( tangyun 发表于 2002-11-16 11:11:00)
 
我没有看过代码,只看了你的实现文档,想提点意见,希望你能参考一下。
   1。什么叫自动管理,创建及删除一个线程就叫自动管理??????
   2。我认为所谓的自动管理应该实现,根据当前的任务量,来实现线程的创建与删除。
   如:在服务器上,当并发客户数增多时,服务器自动增开服务线程。并发客户减少时,自动销毁空闲的线程。 ( 学子 发表于 2002-11-15 13:20:00)
 
asfasdf ( 学子 发表于 2002-11-15 13:12:00)
 
我什么也看不懂! ( jun555_2 发表于 2002-11-14 12:16:00)
 
考虑:

ThreadTask::~ThreadTask()
{
  需要关闭句柄
} ( zfvie 发表于 2002-11-14 11:40:00)
 
一直搞不清同步和异步到底是什么含义。还请polar指教指教!
( zwcboy 发表于 2002-11-13 9:06:00)
 
.......................................................

--------------------next---------------------

阅读(201) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~