C++11 实现简单的线程池

需要提前了解一些C++11的线程知识

需要提前了解,thread 的创建,mutex的基本使用,unique_lock与mutex绑定,函数对象化包装(function),移动语义。

线程池设计思想

线程池首先需要进行初始化,本代码初始化了5个线程(手动指定),开始5个线程会被阻塞,等待任务队列中有任务,任务存储在queue队列中,当队列中有任务的时候,会唤醒一个线程来处理此任务。任务队列大小本程序指定了3个。
MyThreadPool.h

#pragma once
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <vector>
#include <queue>
#define TASKNUM 3
using namespace std;
class ThreadPool
{
public:
    typedef function<void()> Task;  //把调用的函数包装成一个对象。当作一个任务对象
    ThreadPool();
    void initThread(int num);  //初始化线程池启动线程
    void addTask(const Task& t);
    void setsize(int num);  //设置线程数量
    void runTask();    //执行任务
    void Alljoin();    //主线程等待子线程结束
    ~ThreadPool();
private:
    //线程个数
    int m_threadnum;
    //线程数组
    vector<thread> m_threads;
    //任务队列
    queue<Task> m_task;
    //互斥锁
    mutex m_mtx;
    //条件变量
    condition_variable m_cond;    //用于线程的唤醒与等待
    //判断队列对空对满
    bool m_isEmpty;
    bool m_isFull;
 
    //线程池工作结束为真
    bool  m_done;
    
};

MyThreadPool.cpp

#include "ThreadPool.h"
 
 
//初始化变量
ThreadPool::ThreadPool():m_isFull(false),m_isEmpty(true),m_done(false)
{
}
 /** @fn void ThreadPool::start(int num)
 *   @brief 初始化线程池
 *   @param(OUT)  int num 
 *   @param(IN)  int num 
 *   @returns void 
 */
void ThreadPool::initThread(int num)
{
    setsize(num);
    for (int i = 0;i < num; i++)
    {
        m_threads.push_back(thread(&ThreadPool::runTask,this));
    }
}
 
 /** @fn void ThreadPool::addTask(const Task&t)
 *   @brief 添加任务
 *   @param(OUT)  const Task & t 
 *   @param(IN)  const Task & t 
 *   @returns void 
 */
void ThreadPool::addTask(const Task &t)
{
    if (!m_done)   //线程池在工作
    {
        unique_lock<mutex> lk(m_mtx);
        while(m_isFull)   //如果任务队列满了就循环等待  
        {
            m_cond.wait(lk);   
        }
 
        //当队列不满的时候加入到队列中
        m_task.push(t);
        if (TASKNUM == m_task.size())
        {
            m_isFull = true;
        }
        cout <<"Add a task success"<<endl;
        m_isEmpty = false;
        m_cond.notify_one();   //通知一个线程来调用。
    }
}
 
void ThreadPool::setsize(int num)
{
    this->m_threadnum = num;
}
 
 /** @fn void ThreadPool::runTask()
 *   @brief 执行线程入口函数
 *   @returns void 
 */
void ThreadPool::runTask()
{
    while (!m_done)
    {
        unique_lock<mutex> lk(m_mtx);
        while (m_isEmpty)
        {
            m_cond.wait(lk);
        }
        //移动语义
        Task ta;
        ta = move(m_task.front());   //将队列中第一个任务移给ta,进行执行。使用move为了减少内存的频繁创建与释放。
        m_task.pop();
        if (0 == m_task.size())
        {
            m_isEmpty = true;
        }
 
        m_isFull = false;
        m_cond.notify_one();
        lk.unlock();  //在这里解锁在这里其实已经实现了从队列中一个一个的调用任务
        ta();         //任务已经分配了一个线程在执行,不会发生错乱。
    }
 
}
 
 /** @fn void ThreadPool::finish()
 *   @brief 等待子线程退出
 *   @returns void 
 */
void ThreadPool::Alljoin()
{
    for (int i = 0;i < m_threadnum;i++)
    {
        m_threads[i].join();
    }
}
 
ThreadPool::~ThreadPool()
{
}

main.cpp

#include<iostream>
#include "ThreadPool.h"
using namespace std;
 
void func(int i)
{
    cout <<"task finish   "<<i<<"    线程id = "<<this_thread::get_id()<<endl;
}
 
int main(int argc,char *argv[])
{
    ThreadPool p;
    p.initThread(5);  //初始化线程池
    static int num = 0;
 
    while (1) {
        num++;
        //this_thread::sleep_for(chrono::seconds(1));    //延时1s
        auto task = bind(func,num);   //把函数与参数绑定到一起
        p.addTask(task);
    }
 
    p.Alljoin();
    return 0;
}
 

参考博客

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值