C++11 线程池实现

    C++11中已经添加了跨平台的thread相关工具,在一些轻量级使用场景中,使用std::thread无疑会给我们带来很多方便。这里使用它实现了一个简单的线程池:

EasyThreadPool.h
#ifndef _EASY_THREAD_POOL_H_
#define _EASY_THREAD_POOL_H_


#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <vector>
#include <queue>
#include <functional>


class EasyThreadPool
{
  private:
    using Task = std::function<void()>;


  public:
    EasyThreadPool(size_t numThreads = std::thread::hardware_concurrency());
    ~EasyThreadPool();


    //提交任务
    void PostTask(const Task &);


  private:
    std::vector<std::thread> _threads;
    std::queue<Task> _tasks;
    std::mutex _mutex;
    std::condition_variable _cv;
    std::atomic<bool> _isDone;  //是否已停止加入新任务
    std::atomic<bool> _taskEmpty; //任务队列是否已空


    void RunThreadWorker();
    bool GetTask(Task&);
};


#endif // _EASY_THREAD_POOL_H_
EasyThreadPool.cpp
#include "EasyThreadPool.h"
#include <iostream>


EasyThreadPool::EasyThreadPool(size_t numThreads) : _isDone(false), _taskEmpty(true)
{
    try
    {
        for (size_t i = 0; i < numThreads; i++)
        {
            _threads.push_back(std::thread(&EasyThreadPool::RunThreadWorker, this));
        }
    }
    catch (...)
    {
        _isDone.store(true);
        throw;
    }
}


EasyThreadPool::~EasyThreadPool()
{
    _isDone.store(true);
    //唤醒所有线程
    _cv.notify_all();
    for (std::thread &thread : _threads)
    {
        if (thread.joinable())
        {
            thread.join();
        }
    }
}


void EasyThreadPool::PostTask(const Task &task)
{
    if (_isDone)
    {
        std::cout << "The threadPool has been stop!" << std::endl;
    }
    else
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _cv.wait(lock, [this] { return !_isDone; });
        _tasks.push(task);
        _taskEmpty.store(false);
        //唤醒一个线程去执行
        _cv.notify_one();
    }
}


void EasyThreadPool::RunThreadWorker()
{
    Task task;
    //确保任务执行完成后再销毁
    while (!_isDone || !_taskEmpty)
    {
        if (GetTask(task))
        {
            task();
        }
        else
        {
            //暂停一段时间,给别的线程机会
            std::this_thread::yield();
        }
    }
}


bool EasyThreadPool::GetTask(Task &task)
{
    std::unique_lock<std::mutex> lock(_mutex);
    //不满足条件会阻塞
    _cv.wait(lock, [this] { return !_taskEmpty || _isDone; });
    if (!_tasks.empty())
    {
        task = std::move(_tasks.front());
        _tasks.pop();
        _taskEmpty.store(_tasks.empty());
        return true;
    }
    return false;
}
测试实例
// test.cpp


#include "EasyThreadPool.h"
#include <iostream>


void PrintInfo()
{
    std::cout << std::this_thread::get_id() << ": Test" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
}


int main()
{
    EasyThreadPool pool(10);
    int i = 0;
    while (i++ < 100)
    {
        pool.PostTask(PrintInfo);
    }
    return 0;
}
在Linux下使用g++编译:
g++ test.cpp EasyThreadPool.h EasyThreadPool.cpp -o test --std=c++11 -lpthread

    线程池的实现无非就是生产者-消费者模型。使用C++11实现线程池的好处显而易见,相比C,它非常简洁,只有100余行代码就可以搞定。不过它涉及到的锁等线程同步的知识任然很有代表性。

源码地址:EasyThreadPool

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值