操作系统 线程池

先来了解一下线程池的场景 :

我们想创建多个线程  来执行任务  有的时候没有那么多的任务  有的线程就不需要去工作 

就会浪费  我们通常让这样的线程休眠   等到需要她的时候在唤醒   当任务太多 线程不够的时候  我们还可以创建几个   相反  当线程太多 任务太少时   我们还可以杀死几个线程 

达到对线程的动态分配(这一篇还未达到真正的动态分配空间)  (下一篇会完善)

完整代码如下

定义线程池类和任务类:

#ifndef CMYTHREADPOOL_H
#define CMYTHREADPOOL_H
#include<windows.h>
#include<list>
#include<queue>
class Itask
{
public:
    Itask()
    {}
    virtual ~Itask()
    {}
    virtual void RunItask()=0;
};

class cMyThreadPool
{
public:
    cMyThreadPool();

    ~cMyThreadPool();

public:

    //创建线程池
    bool CreateThreadPool(long Min,long Max,long MaxItask);
    //销毁线程池
    void DestroyThreadPool();
    //取出任务
    bool Push(Itask*pItask);
    //线程函数
    static DWORD WINAPI ThreadProc(LPVOID lpvoid);
private:
    //线程链表
    std::list<HANDLE> m_myhandlelist;
    //线程池销毁标记
    bool bFlag;
    //信号量
    HANDLE m_hSemaphore;
    //任务队列
    std::queue<Itask*> m_qitklist;
    //创建的线程数
    long m_lCreateThreadNum;
    //最大线程数
    long m_lMaxThreadNum;
    //运行的线程数
    long m_lRunThreadNum;
    //当前任务数量
    long m_lCurrentItaskNum;
    //最大任务数量
    long m_lMaxItaskNum;
    //互斥量
    HANDLE m_lMutex;
};

#endif // CMYTHREADPOOL_H

#include "cmythreadpool.h"

cMyThreadPool::cMyThreadPool()
{
    bFlag=true;
    m_hSemaphore=NULL;
    m_lCreateThreadNum=NULL;
    m_lMaxThreadNum=NULL;
    m_lRunThreadNum=NULL;
    m_lCurrentItaskNum=NULL;
    m_lMaxItaskNum=NULL;
    m_lMutex=CreateMutex(0,0,0);
}
cMyThreadPool::~cMyThreadPool()
{

}
bool cMyThreadPool::CreateThreadPool(long Min,long Max,long MaxItask)
{
    HANDLE hand;
    if(Min<=0||Max<Min)
        return  false;

    m_hSemaphore=CreateSemaphoreW(0,//安全属性
                                  0,//初始化信号量总数
                                  MaxItask,//最大信号量总数
                                  0//名字
                                  );

    //添加Min个线程到线程池中
    for(long i=0;i<Min;i++)
    {
        hand=CreateThread(0,0,&ThreadProc,this,0,0);
        if(hand)
        {
            m_myhandlelist.push_back(hand);
        }
    }

    //当前线程数为Min个
    m_lCreateThreadNum=Min;
    //最大线程数为我们传进来的Max个
    m_lMaxThreadNum=Max;
    m_lMaxItaskNum= MaxItask;
    return  true;

}

void cMyThreadPool::DestroyThreadPool()
{

    //销毁线程池
    bFlag=false;
    //遍历线程链表  逐个结束进程
    auto ite=m_myhandlelist.begin();
    while(ite!=m_myhandlelist.end())
    {
        if(WAIT_TIMEOUT== WaitForSingleObject(*ite,100))
            //线程未正常 结束  杀死
        TerminateThread(*ite,-1);

        //正常结束  关闭句柄
        CloseHandle(*ite);
        *ite=NULL;

        ite++;
    }
    //清空线程列表
    m_myhandlelist.clear();

    //关闭信号量
        if(m_hSemaphore)
        {
             CloseHandle(m_hSemaphore);
             m_hSemaphore=NULL;
        }

        //关闭互斥量
        if(m_lMutex)
        {
             CloseHandle(m_lMutex);
             m_lMutex=NULL;
        }


        // 任务执行完  回收任务的空间
        Itask *pita=NULL;
        while(m_qitklist.empty())
        {

            pita=m_qitklist.front();
            m_qitklist.pop();

            delete pita;
            pita=NULL;

       }


}

bool cMyThreadPool::Push(Itask*pItask)
{
    //任务的参数校验
    if(pItask==NULL)
        return false;
    //将任务放入任务队列
    if(m_lCreateThreadNum==m_lMaxItaskNum)
    {
        Sleep(10);
    }

    //c++队列不允许同时pop和push  加个锁
    WaitForSingleObject(m_lMutex,INFINITE);
    m_qitklist.push(pItask);
    ReleaseMutex(m_lMutex);



    m_lCurrentItaskNum++;


    //1.如果现在所有的线程都在工作 并且线程的数量没有达到最大值
    //添加一个线程
    if(m_lCreateThreadNum==m_lRunThreadNum&&
           m_lCreateThreadNum <m_lMaxThreadNum)
    {
        HANDLE hand=CreateThread(0,0,&ThreadProc,this,0,0);
        if(hand)
        {
            m_myhandlelist.push_back(hand);
        }
        m_lCreateThreadNum++;
    }
    //2.有空闲线程
    //ReleaseSemaphore(m_hSemaphore,1,NULL);

    //3.线程都在工作 并且线程数量达到最大值
    //ReleaseSemaphore(m_hSemaphore,1,NULL);

    //三种情况都有  ReleaseSemaphore(m_hSemaphore,1,NULL);
    //拿出来  后两种情况被简化了

    ReleaseSemaphore(m_hSemaphore,1,NULL);
    return true;

}

DWORD WINAPI cMyThreadPool::ThreadProc(LPVOID lpvoid)
{
    cMyThreadPool*pthis=(cMyThreadPool*)lpvoid;
    Itask*pita=NULL;
    while(1)
    {
        //等信号
        WaitForSingleObject(pthis->m_hSemaphore,INFINITE);
        //从队列中取出 任务


        //当前正在执行的任务+1
        //这里不允许多个线程同时执行++  采用原子操作
        //pthis->m_lRunThreadNum++;
        InterlockedIncrement(&pthis->m_lRunThreadNum);

        //任务列表不为空 执行任务
        if(!pthis->m_qitklist.empty())
        {

            WaitForSingleObject(pthis->m_lMutex,INFINITE);
            if(pthis->m_qitklist.empty())
            {
                ReleaseMutex(pthis->m_lMutex);
                continue;
            }
            pita=pthis->m_qitklist.front();

            //此任务出队
            pthis->m_qitklist.pop();
            ReleaseMutex(pthis->m_lMutex);

            //执行任务
            pita->RunItask();

            //pthis->m_lCurrentItaskNum--;
            InterlockedDecrement(&pthis->m_lRunThreadNum);

            //回收空间
            delete pita;
            pita=NULL;

       }

        //pthis->m_lRunThreadNum--;
        InterlockedDecrement(&pthis->m_lRunThreadNum);

    }

    return  0;
}

主函数

#include <QCoreApplication>
#include"cmythreadpool.h"
#include<iostream>
using  namespace std;
class Additask:public Itask

{
private:
    int  m_a;
    int  m_b;
public:
    Additask(int  a,int  b)
    {
        m_a=a;
        m_b=b;
    }
    ~Additask()
    {}
    void RunItask()
    {

        cout<<m_a<<"+"<<m_b<<"="<<m_a+m_b<<endl;
    }


};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    cMyThreadPool mt;
    //创建线程池
    mt.CreateThreadPool(10,100,10000);
    //添加100个任务
    for(int i=0;i<10000;i++)
    {
        Itask*add1=new Additask(i,i+1);
        //将任务投递到线程池中
        mt.Push(add1);

        //
        //Sleep(10);
    }




    return a.exec();
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值