一个高效率的线程池类

来源:互联网 发布:pl sql developer教程 编辑:程序博客网 时间:2024/05/18 12:38

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;
}

原创粉丝点击