一个高效率的线程池类

MMORPG游戏服务端线程池类
线程池: 
线程是一种比较昂贵的资源.有些系统为了重用线程.引入了线程池的机制. 
线程池的工作原理如下: 
首先.系统会启动一定数量的线程.这些线程就构成了一个线程池.当有任务要做的时候.系统就从线程池里面选一个空闲的线程.然后把这个线程标记为“正在运行”.然后把任务传给这个线程执行.线程执行任务完成之后.就把自己标记为"空闲".这个过程并不难以理解.难以理解的是.一般来说.线程执行完成之后.运行栈等系统资源就会释放.线程对象就被回收了.一个已经完成的线程.又如何能回到线程池的空闲线程队列中呢? 秘诀就在于.线程池里面的线程永远不会执行完成.线程池里面的线程都是一个无穷循环

ThreadStarter.h


#ifndef __THREADSTARTER_H__
#define  __THREADSTARTER_H__

#include  < windows.h >

// 线程接口
class  ThreadBase
{
public :
    ThreadBase() {}
     virtual   ~ ThreadBase() {}
     virtual   bool  run()  =   0 ; // 线程函数
     virtual   void  OnShutdown() {}
    HANDLE THREAD_HANDLE;
};

#endif

Threads.h


#ifndef __CTHREADS_H__
#define  __CTHREADS_H__

#include  " ThreadStarter.h "

// 线程的状态
enum  CThreadState
{
    THREADSTATE_TERMINATE  =   0 , // 终止
    THREADSTATE_PAUSED     =   1 , // 暂停
    THREADSTATE_SLEEPING   =   2 , // 睡眠
    THREADSTATE_BUSY       =   3 , // 忙碌
    THREADSTATE_AWAITING   =   4 , // 等候
};

// 线程基类
class  CThread :  public  ThreadBase
{

public :
    CThread();
     ~ CThread();
     virtual   bool  run();
     virtual   void  OnShutdown();

     // 设置线程的状态
    __forceinline  void  SetThreadState(CThreadState thread_state)
    { 
        ThreadState  =  thread_state;
    }
     // 返回线程的状态
    __forceinline CThreadState GetThreadState()
    { 
         return  ThreadState;
    }
     // 返回线程ID
     int  GetThreadId()
    { 
         return  ThreadId;
    }
    time_t GetStartTime() 
    {
         return  start_time;
    }

protected :
    CThreadState ThreadState; // 线程的状态
    time_t start_time;
     int  ThreadId; // 线程ID

};

#endif


Threads.cpp


#include  " stdafx.h "
#include  " CThreads.h "

CThread::CThread() : ThreadBase()
{    
     // 初试化线程的状态为等候
    ThreadState  =  THREADSTATE_AWAITING;
    start_time   =   0 ;
}

CThread:: ~ CThread()
{
    
}

bool  CThread::run()
{
     return   false ;
}

void  CThread::OnShutdown()
{
    SetThreadState(THREADSTATE_TERMINATE);
}

Mutex.h


#ifndef __MUTEX_H__
#define  __MUTEX_H__

#include  < windows.h >

// 多个线程操作相同的数据时,一般是需要按顺序访问的,否则会引导数据错乱
// 为解决这个问题,就需要引入互斥变量,让每个线程都按顺序地访问变量。
class  Mutex
{
public :
    Mutex();
     ~ Mutex();

    __forceinline  void  Acquire()
    {
        EnterCriticalSection( & cs);
    }

    __forceinline  void  Release()
    {
        LeaveCriticalSection( & cs);
    }
     /*
    例如:
    线程操作函数。
    int AddCount(void)
    {
        EnterCriticalSection(&cs);
        int nRet = m_nCount++;
        LeaveCriticalSection(&cs);
        return nRet;
    }
    在函数AddCount里调用EnterCriticalSection和LeaveCriticalSection来互斥访问变量m_nCount。
    通过上面这种方法,就可以实现多线程按顺序地访问相同的变量
     */
    __forceinline  bool  AttemptAcquire()
    {
         // 一个线程也可以调用TryEnterCriticalSection函数来请求某个临界区的所有权,此时即
         // 使请求失败也不会被阻塞
         return   0 ; // (TryEnterCriticalSection(&cs) == TRUE ? true : false);
    }

protected :
    CRITICAL_SECTION cs; // 临界区是一种防止多个线程同时执行一个特定代码节的机制

};

#endif

Mutex.cpp


#include  " stdafx.h "
#include  " Mutex.h "
 
Mutex::Mutex() 
{
     // 创建临界区对象
    InitializeCriticalSection( & cs);
}
Mutex:: ~ Mutex()
{
     // 删除临界区对象
    DeleteCriticalSection( & cs);
}

ThreadPool.h


#ifndef __THREADPOOL_H__
#define  __THREADPOOL_H__

#include  " ThreadStarter.h "
#include  " Mutex.h "

#include  < windows.h >
#include  < assert.h >
#include  < set >


typedef unsigned  int  uint32;
typedef signed __int32 int32;

// 线程管理
class  ThreadController
{
public :
    HANDLE hThread;
    uint32 thread_id;

     void  Setup(HANDLE h)
    {
        hThread  =  h;
    }
     void  Suspend()
    {
        assert(GetCurrentThreadId()  ==  thread_id);
         // 当线程做完任务或者现在想暂停线程运行,就需要使用SuspendThread来暂停线程的执行
        SuspendThread(hThread);
        
    }

     // 恢复线程的执行就是使用ResumeThread函数了
     void  Resume()
    {
        assert(GetCurrentThreadId()  !=  thread_id);
         if ( ! ResumeThread(hThread))
        {
            DWORD le  =  GetLastError();
            printf( " error: %u/n " , le);
        }
    }

     void  Join()
    {
         // WaitForSingleObject函数用来检测hHandle事件的信号状态,当函数的执行时间超过dwMilliseconds就返回
        WaitForSingleObject(hThread, INFINITE);
    }

    uint32 GetId()
    {
         return  thread_id;
    }

};

struct  Thread
{
    ThreadBase *  ExecutionTarget;
    ThreadController ControlInterface;
    Mutex SetupMutex; // 线程的互斥
     bool  DeleteAfterExit;
};

typedef std:: set < Thread *>  ThreadSet;

// 线程池类
class  CThreadPool
{
     // uint32 _threadsRequestedSinceLastCheck;
     // uint32 _threadsFreedSinceLastCheck;
     // uint32 _threadsExitedSinceLastCheck;
    uint32 _threadsToExit;
    int32 _threadsEaten; // 可用线程数量
    Mutex _mutex;

    ThreadSet m_activeThreads; // 正在执行任务线程对列
    ThreadSet m_freeThreads; // 可用线程对列

public :
    CThreadPool();

     void  IntegrityCheck();

     // 创建指定数量的线程并加到线程池
     void  Startup();

     // 销毁线程
     void  Shutdown();
    

     bool  ThreadExit(Thread  *  t);

    Thread *  StartThread(ThreadBase  *  ExecutionTarget);

     // 从线程池取得可用线程并执行任务
     void  ExecuteTask(ThreadBase  *  ExecutionTarget);

     void  ShowStats();

    
     void  KillFreeThreads(uint32 count);

    
     // __forceinline void Gobble(){ 
     //     _threadsEaten=(int32)m_freeThreads.size();
     // }

    __forceinline uint32 GetActiveThreadCount(){
         return  (uint32)m_activeThreads.size();
    }

    __forceinline uint32 GetFreeThreadCount(){
         return  (uint32)m_freeThreads.size();
    }
};

extern  CThreadPool ThreadPool; // 线程池

#endif

ThreadPool.cpp


#include  " stdafx.h "
#include  " ThreadPool.h "
#include  < process.h >

CThreadPool ThreadPool;

CThreadPool::CThreadPool()
{
     // _threadsExitedSinceLastCheck = 0;
     // _threadsRequestedSinceLastCheck = 0;
    _threadsEaten  =   0 ;
     // _threadsFreedSinceLastCheck = 0;
}


bool  CThreadPool::ThreadExit(Thread  *  t)
{
    _mutex.Acquire();
    
    m_activeThreads.erase(t);

     if (_threadsToExit  >   0 )
    {
         -- _threadsToExit;
         // ++_threadsExitedSinceLastCheck;
         if (t -> DeleteAfterExit)
            m_freeThreads.erase(t);

        _mutex.Release();
        delete t;
         return   false ;
    }


     //  enter the "suspended" pool
     // ++_threadsExitedSinceLastCheck;
     ++ _threadsEaten;
    std:: set < Thread *> ::iterator itr  =  m_freeThreads.find(t);

     if (itr  !=  m_freeThreads.end())
    {
        
    }
    m_freeThreads.insert(t);
    
    _mutex.Release();

     return   true ;


}


void  CThreadPool::ExecuteTask(ThreadBase  *  ExecutionTarget)
{

    Thread  *  t;
    _mutex.Acquire();
     // ++_threadsRequestedSinceLastCheck;
     -- _threadsEaten;

     // 从线程池夺取一个线程
     if (m_freeThreads.size()) // 有可用线程
    {    
         // 得到一个可用线程
        t  =   * m_freeThreads.begin();
         // 把它从可用线程对列里删掉
        m_freeThreads.erase(m_freeThreads.begin());

         // 给这个线程一个任务
        t -> ExecutionTarget  =  ExecutionTarget;
        
         // 恢复线程的执行
        t -> ControlInterface.Resume();
    }
     else
    {

         // 创建一个新的线程并执行任务
        t  =  StartThread(ExecutionTarget);
    }

     // 把线程加到执行任务线程对列
    m_activeThreads.insert(t);
    _mutex.Release();


}

void  CThreadPool::Startup()
{
     int  i;
     int  tcount  =   5 ;

     for (i = 0 ; i  <  tcount;  ++ i)
        StartThread(NULL);

}

void  CThreadPool::ShowStats()
{
    _mutex.Acquire();

     // 在这里输出线程池的状态
     //

    _mutex.Release();
}

void  CThreadPool::KillFreeThreads(uint32 count)
{
    _mutex.Acquire();
    Thread  *  t;
    ThreadSet::iterator itr;
    uint32 i;
     for (i  =   0 , itr  =  m_freeThreads.begin(); i  <  count  &&  itr  !=  m_freeThreads.end();  ++ i,  ++ itr)
    {
        t  =   * itr;
        t -> ExecutionTarget  =  NULL; 
        t -> DeleteAfterExit  =   true ;
         ++ _threadsToExit;
        t -> ControlInterface.Resume();
    }
    _mutex.Release();
}

void  CThreadPool::Shutdown()
{
    _mutex.Acquire();
    size_t tcount  =  m_activeThreads.size()  +  m_freeThreads.size();        
    
    KillFreeThreads((uint32)m_freeThreads.size());
    _threadsToExit  +=  (uint32)m_activeThreads.size();

     for (ThreadSet::iterator itr  =  m_activeThreads.begin(); itr  !=  m_activeThreads.end();  ++ itr)
    {
         if (( * itr) -> ExecutionTarget)
            ( * itr) -> ExecutionTarget -> OnShutdown();
    }
    _mutex.Release();

     for (;;)
    {
        _mutex.Acquire();
         if (m_activeThreads.size()  ||  m_freeThreads.size())
        {
            _mutex.Release();
            Sleep( 1000 );
             continue ;
        }

         break ;
    }
}


static  unsigned  long  WINAPI thread_proc( void *  param)
{
    Thread  *  t  =  (Thread * )param;
    t -> SetupMutex.Acquire();
    uint32 tid  =  t -> ControlInterface.GetId();
     bool  ht  =  (t -> ExecutionTarget  !=  NULL);
    t -> SetupMutex.Release();
    
     for (;;)
    {
         if (t -> ExecutionTarget  !=  NULL)
        {
             if (t -> ExecutionTarget -> run()) // 执行任务,返回true表示任务完成
                delete t -> ExecutionTarget;

            t -> ExecutionTarget  =  NULL;
        }

         if ( ! ThreadPool.ThreadExit(t))
        {
             // Log.Debug("ThreadPool", "Thread %u exiting.", tid);
             break ;
        }
         else
        {
             // if(ht)
             //     printf("ThreadPool:线程%d正在等待新任务.", tid);
            t -> ControlInterface.Suspend(); // 暂停线程运行
        }
    }

    ExitThread( 0 );

     return   0 ;
}

Thread  *  CThreadPool::StartThread(ThreadBase  *  ExecutionTarget)
{
    HANDLE h;
    Thread  *  t  =   new  Thread;
    
    t -> DeleteAfterExit  =   false ;
    t -> ExecutionTarget  =  ExecutionTarget;
    t -> SetupMutex.Acquire();
     /*
    CreateThread(
    lpThreadAttributes是线程的属性,
    dwStackSize是线程的栈大小,
    lpStartAddress是线程函数的开始地址,
    lpParameter是传送给线程函数的参数,
    dwCreationFlags是创建线程标志,比如挂起线程,
    lpThreadId是标识这个线程的ID)
     */
    h  =  CreateThread(NULL,  0 ,  & thread_proc, (LPVOID)t,  0 , (LPDWORD) & t -> ControlInterface.thread_id);
    t -> ControlInterface.Setup(h);
    t -> SetupMutex.Release();
 
     return  t;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值