快速入门,C++线程池实现,看不懂来打我!

 写在前面:本回答是简单线程池的讲解和实现:下个版本的线程池在这个回答里

目录 

1.写出一个单例

2.设计函数

3.设计一个线程池,一个任务队列

4.使用Linux信号量

5.任务存放到任务队列中并使用 sem_post( ) 通知 sem_wait( ) ;

6.收到通知,从任务队列中取出任务并执行

7.开启线程池,往线程池里添加N个线程

8.附源码


1.写出一个单例

class Threadpool
{
private:
    Threadpool(){}
    static Threadpool threadpool;

public:
    static Threadpool* getInstance(){ return &threadpool; } 
};
Threadpool Threadpool::threadpool;

其中最容易忽视的一句是:Threadpool Threadpool::threadpool;

2.设计函数

public:
void start();

void addTask(Task task);

private:
void runTask();
//用于给start绑定

3.设计一个线程池,一个任务队列

std::vector<std::thread> threadList;//线程池

//任务队列
using Task = std::function<void()>;
std::queue<Task> taskQueue;

4.使用Linux信号量

::sem_t taskSem;

::sem_init(&taskSem, 0, 0);

::sem_post(&taskSem);

::sem_wait(&taskSem);

5.任务存放到任务队列中并使用 sem_post( ) 通知 sem_wait( ) ;

taskQueue.push(task);

::sem_post(&taskSem);
//信号量+1

6.收到通知,从任务队列中取出任务执行

::sem_wait(&taskSem);
//收到通知开始执行

Task task = taskQueue.front();
//拿到第一个任务

taskQueue.pop();
//丢弃第一个任务

task();
//执行第一个任务

7.开启线程池,往线程池里添加N个线程

for(int i = 0; i < threadNums; ++i)
   {
        threadList.emplace_back(std::thread(&Threadpoll::runTask, this));
   }

8.附源码

#include <semaphore.h>
#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
#include <vector>
#include <queue>

::sem_t taskSem;
int threadNums = 10;

class Threadpool
{
private:
    Threadpool()
    {
        ::sem_init(&taskSem, 0, 0);
    }
    static Threadpool threadpool;

private:
    std::vector<std::thread> threadList;

    using Task = std::function<void()>;
    std::queue<Task> taskQueue;

public:
    static Threadpool* getInstance(){ return &threadpool; } 

    void start()
    {
        for(int i = 0; i < threadNums; i++)
        {
            threadList.emplace_back(std::thread(Threadpool::runTask, this));
        }
    }

    void addTask(Task task)
    {
        taskQueue.push(task);

        ::sem_post(&taskSem);
    }
private:
    void runTask()
    {
        ::sem_wait(&taskSem);
        
        Task task = taskQueue.front();

        taskQueue.pop();

        task();
    }
};
Threadpool Threadpool::threadpool;
//这句话很重要

9.测试

int main()
{
    auto threadpool = Threadpool::getInstance();

    threadpool->start();
    
    while(true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(2));

        threadpool->addTask(
            [](){std::cout << "addTask" << std::endl;}
        );
    }

    return 0;
}

10.还需完善的地方

本例子迭代过两次:实现了

  1. linux函数前面加了::,
  2. task改为Task,
  3. 绑定函数使用了lambda表达式,
  4. 去除using namespace std;
  5. 使用了更加规范的命名方式
  6. 注意了单例模式必须要在类外声明出来一个实例,且目前不能为指针

没有考虑

  1. 单例模式的线程安全,这是一个饿汉单例模式
  2. 没有使用C++11的条件变量,C++11条件变量的实现
  3. thread没有join,而且去除while(true)会出现bug
  4. 不理解C++线程的join和notify究竟在上面时候使用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值