线程池ThreadPool封装测试

1、ThreadPool

#ifndef _ThreadPool_H_
#define _ThreadPool_H_

#pragma warning(disable: 4530)
#pragma warning(disable: 4786)

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

class ThreadTask  //任务基类
{
public:
    //供线程池调用的虚函数
    virtual void DoTask(void* pPara) = 0;
};

class ThreadPool
{

public:
    //================================构造及核心外部可调用接口函数==================================
    //1.构造函数:创建线程。dwNum 线程池规模
    ThreadPool(DWORD dwNum = 4) : _lThreadNum(0), _lRunningNum(0)
    {
        //初始化2个临界区:线程数据临界区,工作队列(任务队列)临界区
        InitializeCriticalSection(&_csThreadVector);
        InitializeCriticalSection(&_csTaskQueue);

        //创建2个事件、2个信号量:完成事件, 结束通知事件, 工作信号, 删除线程信号
        _EventComplete = CreateEvent(0, false, false, NULL);
        _EventEnd = CreateEvent(0, true, false, NULL);
        _SemaphoreCall = CreateSemaphore(0, 0, 0x7FFFFFFF, NULL);
        _SemaphoreDel = CreateSemaphore(0, 0, 0x7FFFFFFF, NULL);

        assert(_SemaphoreCall != INVALID_HANDLE_VALUE);
        assert(_EventComplete != INVALID_HANDLE_VALUE);
        assert(_EventEnd != INVALID_HANDLE_VALUE);
        assert(_SemaphoreDel != INVALID_HANDLE_VALUE);

        //创建dwNum个工作线程
        AdjustSize(dwNum <= 0 ? 4 : dwNum);
    }

    ~ThreadPool()
    {
        DeleteCriticalSection(&_csTaskQueue);//删除工作队列临界区

        //关闭事件、信号量
        CloseHandle(_EventEnd);
        CloseHandle(_EventComplete);
        CloseHandle(_SemaphoreCall);
        CloseHandle(_SemaphoreDel);

        vector::iterator iter;
        //删除所有线程
        for (iter = _ThreadVector.begin(); iter != _ThreadVector.end(); iter++)
        {
            if (*iter)
                delete* iter;
        }

        DeleteCriticalSection(&_csThreadVector);//删除线程数据临界区
    }
    //2.创建线程:调整线程池规模
    int AdjustSize(int iNum)
    {
        if (iNum > 0)
        {
            ThreadItem* pNew;
            EnterCriticalSection(&_csThreadVector);
            for (int _i = 0; _i < iNum; _i++)
            {
                _ThreadVector.push_back(pNew = new ThreadItem(this));
                assert(pNew);
                //创建线程:调用线程函数DefaultTaskProc
                pNew->_Handle = CreateThread(NULL, 0, fnDefaultTaskProc, pNew, 0, NULL);
                assert(pNew->_Handle);
            }
            LeaveCriticalSection(&_csThreadVector);
        }
        else
        {
            iNum *= -1;
            ReleaseSemaphore(_SemaphoreDel, iNum > _lThreadNum ? _lThreadNum : iNum, NULL);
        }
        return (int)_lThreadNum;
    }
    //3.调用线程池方法1
    void Call(void (*pFunc)(void*), void* pPara = NULL)
    {
        assert(pFunc);

        EnterCriticalSection(&_csTaskQueue);
        _TaskQueue.push(new TaskItem(pFunc, pPara));//工作队列中添加任务
        LeaveCriticalSection(&_csTaskQueue);

        //对指定的信号量(参数一)增加指定的值(参数二:在当前基础上所要增加的值)
        ReleaseSemaphore(_SemaphoreCall, 1, NULL);//工作信号 通知线程池有工作
    }
    //4.调用线程池方法2
    inline void Call(ThreadTask* p, void* pPara = NULL)
    {
        Call(fnCallProc, new CallProcPara(p, pPara));
    }
    //=====================================================================================

    //=========================else:其他外部接口可调用函数==================================
    //结束线程池, 并同步等待
    bool EndAndWait(DWORD dwWaitTime = INFINITE)
    {
        SetEvent(_EventEnd);
        return WaitForSingleObject(_EventComplete, dwWaitTime) == WAIT_OBJECT_0;//等待 完成事件
    }
    //结束线程池
    inline void End()
    {
        SetEvent(_EventEnd);//线程池结束事件
    }
    inline DWORD Size()
    {
        return (DWORD)_lThreadNum;//线程数
    }
    inline DWORD GetRunningSize()
    {
        return (DWORD)_lRunningNum;//运行的线程数
    }
    bool IsRunning()
    {
        return _lRunningNum > 0;
    }
    //=======================================================================================

protected:
    //=============================核心内部成员函数===========================================
    //1.工作线程()
    static DWORD WINAPI fnDefaultTaskProc(LPVOID lpParameter = NULL)
    {
        ThreadItem* pThread = static_cast(lpParameter);//转型为线程对象指针
        assert(pThread);

        ThreadPool* pThreadPoolObj = pThread->_pThis;//线程对象中的线程池
        assert(pThreadPoolObj);

        //1. 增加线程计数
        InterlockedIncrement(&pThreadPoolObj->_lThreadNum);

        HANDLE hWaitHandle[3];
        hWaitHandle[0] = pThreadPoolObj->_SemaphoreCall;//工作信号
        hWaitHandle[1] = pThreadPoolObj->_SemaphoreDel;//删除线程信号
        hWaitHandle[2] = pThreadPoolObj->_EventEnd;//结束线程信号

        TaskItem* pTask = NULL;//用户任务
        bool bHasTask;// 是否还有任务

        for (;;)
        {
            DWORD wr = WaitForMultipleObjects(3, hWaitHandle, false, INFINITE);//等待 工作信号, 删除线程信号, 结束线程信号

            //1.1 收到并响应删除线程信号  hWaitHandle[1] = _SemaphoreDel
            if (wr == WAIT_OBJECT_0 + 1)
                break;

            //从队列里取得用户任务
            EnterCriticalSection(&pThreadPoolObj->_csTaskQueue);
            if (bHasTask = !pThreadPoolObj->_TaskQueue.empty())
            {
                pTask = pThreadPoolObj->_TaskQueue.front();//从队列头取得任务
                pThreadPoolObj->_TaskQueue.pop();//从队列中弹出任务
                assert(pTask);
            }
            LeaveCriticalSection(&pThreadPoolObj->_csTaskQueue);

            //必须要先从队列取任务,之后才能判断是否有工作:
            //1.2收到结束线程信号 确定是否结束线程(结束线程信号 && 没有工作) hWaitHandle[2] = _EventEnd
            if (wr == WAIT_OBJECT_0 + 2 && !bHasTask)
                break;

            if (bHasTask && pTask)//有任务 并且 任务非空
            {
                //InterlockedIncrement、InterlockedDecrement对整型变量进行原子增加和减少操作
                InterlockedIncrement(&pThreadPoolObj->_lRunningNum);//运行的线程数+1
                pThread->_dwLastBeginTime = GetTickCount();//记录线程开始时间
                pThread->_dwCount++;//运行次数+1
                pThread->_fIsRunning = true;

                //==========回调主线程中的线程函数===================
                pTask->_pFunc(pTask->_pPara); //运行用户任务
                //=================================================

                //运行任务结束, 释放资源
                delete pTask;
                pThread->_fIsRunning = false;
                InterlockedDecrement(&pThreadPoolObj->_lRunningNum);
            }
        }

        //删除自身结构
        EnterCriticalSection(&pThreadPoolObj->_csThreadVector);//线程数据临界
        //  std::vector  _ThreadVector; //线程数据
        //线程数据数组中:删除该线程pThread
        pThreadPoolObj->_ThreadVector.erase(find(pThreadPoolObj->_ThreadVector.begin(), pThreadPoolObj->_ThreadVector.end(), pThread));
        LeaveCriticalSection(&pThreadPoolObj->_csThreadVector);

        delete pThread;//删除线程句柄
        
        //2.线程计数减1
        InterlockedDecrement(&pThreadPoolObj->_lThreadNum);

        if (!pThreadPoolObj->_lThreadNum)  //如果线程数为空,说明所有线程结束
            SetEvent(pThreadPoolObj->_EventComplete);//完成事件 激活,通知调用者

        return 0;
    }
    //2.调用用户对象虚函数
    static void fnCallProc(void* pPara)
    {
        CallProcPara* cp = static_cast(pPara);//类型转换
        assert(cp);
        if (cp)//非空
        {
            cp->_pObj->DoTask(cp->_pPara);//运行用户任务
            delete cp;
        }
    }
    //=======================================================================================

    //=============================结构体成员变量=============================================
    //用户对象结构
    struct CallProcPara
    {
        ThreadTask* _pObj;//用户对象
        void* _pPara;//用户参数

        CallProcPara(ThreadTask* p, void* pPara) : _pObj(p), _pPara(pPara) {};
    };
    //用户任务 结构:线程函数指针、参数
    struct TaskItem
    {
        void (*_pFunc)(void*);//线程函数
        void* _pPara; //函数参数
        TaskItem(void (*pFunc)(void*) = NULL, void* pPara = NULL) : _pFunc(pFunc), _pPara(pPara) {};
    };
    //线程结构:就是线程 及 线程相关信息
    struct ThreadItem
    {
        HANDLE _Handle; //线程句柄
        ThreadPool* _pThis;  //线程池的指针
        DWORD _dwLastBeginTime; //最后一次运行开始时间
        DWORD _dwCount; //运行次数
        bool _fIsRunning;//当前线程运行状态

        ThreadItem(ThreadPool* pthis) : _pThis(pthis), _Handle(NULL), _dwLastBeginTime(0), _dwCount(0), _fIsRunning(false) {};
        ~ThreadItem()
        {
            if (_Handle)
            {
                CloseHandle(_Handle);//关闭线程句柄
                _Handle = NULL;
            }
        }
    };
    //=======================================================================================

    //================================成员变量================================================
    std::queue _TaskQueue;  //任务队列
    std::vector  _ThreadVector; //线程数据

    CRITICAL_SECTION _csThreadVector, _csTaskQueue; //线程数据临界,任务队列临界
    HANDLE _EventEnd, _EventComplete, _SemaphoreCall, _SemaphoreDel;//结束通知, 完成事件, 任务信号, 删除线程信号
    long _lThreadNum, _lRunningNum; //线程数, 运行的线程数
    //=======================================================================================
};
#endif //_ThreadPool_H_

2、测试

//ThreadPool tp;
//for (i = 0; i < 100; i++)
//    tp.Call(threadfunc);
//
//ThreadPool tp(20);//20为初始线程池规模
//tp.Call(threadfunc, lpPara);
//tp.AdjustSize(50);//增加50
//tp.AdjustSize(-30);//减少30

void threadfunc(void* p)
{
    //...
    std::cout << "线程ID: " << std::this_thread::get_id() << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

int main()
{
    ThreadPool tp(2);
    for (int i = 0; i < 20; i++)
    {
        tp.Call(threadfunc);
    }
    
    std::cout << "运行的线程数: " << tp.GetRunningSize() << std::endl;
    std::cout << "是否运行: " << tp.IsRunning() << std::endl;
    std::cout << "线程池规模: " << tp.Size() << std::endl;

    tp.EndAndWait();

    std::cout << "线程池规模: " << tp.Size() << std::endl;
    std::cout << "运行的线程数: " << tp.GetRunningSize() << std::endl;
    std::cout << "是否运行: " << tp.IsRunning() << std::endl;

    system("pause");
    return 0;
}

结果:

线程池ThreadPool封装测试_第1张图片

2、

你可能感兴趣的:(#,线程,线程池)