windows下线程池的设计与实现

2280阅读 0评论2013-10-15 qizheguang
分类:WINDOWS

2006转眼就要过去了,今天是2006年最后一天,特此总结一下关于线程池的设计与实现,与各位大虾共享,也算是给所有认识的、不认识的朋友,一个小小礼物。嘎嘎。

         言归正传,我们先来说说线程池的相关概念。

一、什么是池。

池的英文名:POOL,可以理解个容器,一个水缸。打个比方,我小时住在农村,家里都有个水缸,父母会每天早上从湖里,跳水倒满水缸,这样一天的生活用水就准备好了。当我们用水的时候,只需要从水缸里,舀水即可,而不用从湖里去取。这样你现在也许就会明白了,有了池,效率明显高了。在软件中,存在多种池,如线程池,内存池,数据库连接池等等。根据实现的软件需求,这些池将极大提高软件效率。

 

二、什么线程池

上面我们讲述了什么池,那么现在来说明一下,什么是线程池。线程池,也就是在这个池里,预先放入一些线程,以后后来方便使用。

 

三、为什么要使用线程池

我们都知道线程的频繁创建、销毁,是需要耗费一点的系统资源的,所以预先创建一系列空线程,需要使用线程时,从线程池里,获取IDLE线程,这样执行起来效率就非常高了,也便于管理。

 

四、线程池需要具备的几个元素

1)  线程池要有个列表,来管理多个线程对象。

2)  线程池要提供获取空闲(IDLE)线程方法

3)  线程池中的线程,具体执行的内容,可自定义。

4)  线程池中的线程,使用完毕后,还能被收回,供下次使用。

 

下面是我简要来设计线程池如何实现,朋友们可以根据此版本进行扩充或者改进。本BLOG所讲述的线程池实现主要包含3个类:

1)  TEricThreadManager

线程管理类,此对象在创建时,并默认创建NCEricWorkThread线程,并且这些线程状态都是IDLE,表示都可以被使用的。

方法JoinTask,是TEricThreadManager非常重要的方法,用于向线程池中,提取一个空闲(IDLE)线程,执行某个特定的任务。

         实现如下:

//加入一个任务

bool CEricThreadPoolManager::JoinTask(CEricThread* pEricThreadObj)

{

   CEricWorkThread *pEricWorkThread = GetIdleThread();

 

   if (pEricWorkThread == NULL)

   {

        return FALSE;

   }

  

   pEricWorkThread->RunTask(pEricThreadObj);

 

   return TRUE;

}

         方法GetIdleThread,用于从线程队列中,获取一个空闲线程使用。此方法在线程池的设计中,也是必不可少的。

//得到空闲线程

CEricWorkThread* CEricThreadPoolManager::GetIdleThread()

{

   POSITION pos = NULL;

  

   CEricWorkThread *pEricWorkThread = NULL;

   for( pos = m_lstThreads.GetHeadPosition(); pos != NULL; )

   {

         pEricWorkThread = (CEricWorkThread *)m_lstThreads.GetNext( pos );

         if (pEricWorkThread->IsIdle())

         {

              return pEricWorkThread;

         }

   }

 

     return NULL;

}

 

2)  CEricWorkThread

刚才我们讲述了,线程池中的“线程管理类”,现在我们接着来讲述一下,线程池另外非常重要的类CEricWorkThread,它其实就是一个线程类。在CEricWorkThread类对象创建时,自动创建一个线程实例,此时此线程是个空线程。此线程实现如下:

//工作线程

DWORD WINAPI CEricWorkThread::DefaultJobProc(LPVOID lpParameter )

{

  CEricWorkThread *pThis = (CEricWorkThread*)lpParameter;

  HANDLE hWaitHandle[2];

  hWaitHandle[0] = pThis->m_hEventRun;

  hWaitHandle[1] = pThis->m_hEventExit;

 

  for(;;)

  {

      DWORD wr = WaitForMultipleObjects(2, hWaitHandle, false, INFINITE);

 

      if (wr == WAIT_OBJECT_0)  //执行RUN

      {

          pThis->m_bIdle = FALSE; //线程不空闲

          pThis->m_pRunObject->Run();

          //释放此对象

          delete pThis->m_pRunObject;

          pThis->m_pRunObject = NULL;

          pThis->m_bIdle = TRUE; //线程空闲

      }

      else if (wr == WAIT_OBJECT_0+1) //退出线程

      {

         break;

      }

  }

  return 0;

}

 

我们看到,当线程需要执行某个特定任务时,调用下面的语句来执行。

pThis->m_pRunObject->Run();

 

CEricWorkThread类有个非常重要的方法

     bool RunTask(CEricThread *pEricThread);

         用来制定特定的任务,并执行此任务。

 

3)  TEricThread

TEricThread类是具体任务执行类的基类,它有个虚方法

          //线程函数中执行体

virtual void Run()=0;

来表示具体动作。

 

我们可以通过继承TEricThread类,来自定义各种动作。

 

线程池中的核心类,就介绍完毕了。朋友们可以根据如上所说,来搭建自己的线程池。

 

--------------------------------------------------------

by victor:

linux下也可以按照这样的思路来设计线程池。

上一篇:STUN协议
下一篇:编写安全代码——sendto和recvfrom的坑