C++实现线程池

6人阅读 评论(0) 收藏 举报
分类:

C++实现线程池

背景

  • 线程池,或者任务队列是多线程环境下的一种重要的基础组件

功能需求

  • 实现一个任务队列,用来存放当前的任务
  • 当有任务送入时,送入任务队列并提示所有线程,处理库存任务

涉及概念

  • 主要使用了C++11新增的多线程库中的内容;没接触过的话可能比较难以理解,尤其是future\package_task\result_of,除了result_of是用来进行类型推导的,其他主要用于线程的同步,具体可见C++并发指南系列博客
  • std::future
  • std::thread
  • std::package_task
  • std::mutex
  • std::condition_variable
  • std::result_of
  • std::unique_lock

类设计

  • 类名:ThreadPool
  • 成员变量:
    • std::vector workers:线程池中的线程
    • std::queue

代码实现

  • ThreadPool.h
#pragma once
#include <future>
#include <vector>
#include <queue>

class ThreadPool
{
public:
    ThreadPool(size_t); // construct

    template <typename F, typename ... Args>
    auto enqueue(F&& f, Args&& ... args)    
        ->std::future<typename std::result_of<F(Args...)>::type>;   

    ~ThreadPool();

private:
    std::vector<std::thread> workers;
    std::queue<std::function<void()>> tasks;    

    std::mutex queue_mutex;
    std::condition_variable condition;
    bool stop;
};


inline ThreadPool::ThreadPool(size_t threads) : stop(false)
{
    for (size_t i = 0; i < threads; ++i)
    {
        workers.emplace_back(
            [this]
        {
            for (;;)
            {
                std::function<void()> task;
                {
                    std::unique_lock<std::mutex> lock(this->queue_mutex);
                    this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); });
                    if (this->stop&&this->tasks.empty())
                    {
                        return;
                    }
                    task = std::move(this->tasks.front());
                    this->tasks.pop();
                }
                task();
            }
        }
        );

    }
}

inline ThreadPool::~ThreadPool()
{
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        stop = true;
    }
    condition.notify_all();
    for (std::thread& worker : workers)
    {
        worker.join();
    }
}

template <typename F, typename ... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type>
{
    using return_type = typename std::result_of<F(Args...)>::type;
    auto task = std::make_shared<std::packaged_task<return_type() >>(
        std::bind(std::forward<F>(f), std::forward<Args>(args)...)
    );
    std::future<return_type> res = task->get_future();
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        if (stop)
        {
            throw std::runtime_error("enqueue on stopping the pool");
        }
        tasks.emplace([task]() { (*task)(); });
    }
    condition.notify_one();
    return res;
}

使用

  • 使用示例:
#include "ThreadPool.h"
#include <vector>
#include <iostream>
#include <chrono>

int main()
{
    ThreadPool pool(4);
    std::vector<std::future<int>> results;

    for (int i = 0; i < 8; ++i)
    {
        results.emplace_back(
            pool.enqueue([i] {
                std::this_thread::sleep_for(std::chrono::seconds(1));
                return i*i;
            })
        );
    }
    std::this_thread::sleep_for(std::chrono::seconds(3));
    for (auto && result : results)
    {
        std::cout << result.get() << ' ';
    }
    std::cout << std::endl;
    system("pause");
    return 0;
}

总结

  • 线程池的实现本质上并不复杂,需要注意各个操作的原子性
  • 本实现的特点是完全使用C++11的现代标准库进行实现,涉及了库、lambda表达式、模板编程等概念,虽然代码短小,但是要完全理解并不容易
  • 通过模仿、实现、测试,进一步理解,确实收获很多,所以将自己的学习经验分享出来,供来者鉴
查看评论

线程池原理及创建并C++实现

本文给出了一个通用的线程池框架,该框架将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关。另外该线程池具有动态伸缩性,它能根据执行任务的轻重自动调整线程池中线程的数量。文章的最后,我们...
  • shaderdx
  • shaderdx
  • 2016-12-16 15:40:14
  • 4693

[C++][线程池][完整实现] 转:线程池原理及创建(C++实现)

文章的主要框架是参考这篇文档的,http://jacky-dai.iteye.com/blog/1090285, 关于作者  张中庆,西安交通大学软件所,在读硕士,目前研究方向为分布式网络与移动中...
  • yfcheng_yzc
  • yfcheng_yzc
  • 2017-01-09 19:14:56
  • 3552

基于c++11的100行实现简单线程池

背景刚粗略看完一遍c++ primer第五版,一直在找一些c++小项目练手,实验楼里面有很多项目,但是会员太贵了,学生党就只能google+github自行搜索完成项目了。注:本文纯提供自己的理解,代...
  • gcola007
  • gcola007
  • 2017-12-08 12:10:08
  • 1061

C++实现简单线程池

欢迎转载,转载请注明原出处:http://blog.csdn.NET/ithzhang/article/details/9020283            代码地址:https://github....
  • zjc156m
  • zjc156m
  • 2016-09-29 17:23:05
  • 707

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

我想用C语言写过线程池的朋友因该都知道用C语言写一个线程池有多么的麻烦,代码差不多300行左右,而且不易阅读。记得大二寒假第一次写线程池用的就是C语言,当时先参考了别人用C写的代码,说实话看起来真困难...
  • Shreck66
  • Shreck66
  • 2015-12-27 16:50:46
  • 3639

一个简单的线程池的实现(C++)

线程池的原理大家都知道,直接上代码了^_^ Thread.h [cpp] view plaincopyprint? #ifndef __THREAD_H #define __THREAD_...
  • u011676589
  • u011676589
  • 2013-10-10 10:33:06
  • 3806

线程池原理及创建(C++实现)

  • 2010年08月27日 12:47
  • 201KB
  • 下载

linux c++线程池的实现(多线程服务器)

本 文给出了一个通用的线程池框架,该框架将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关。另外该线程池具有动态伸缩性,它能根据执行 任务的轻重自动调整线程池中线程的数量。文章的最后,...
  • u011412619
  • u011412619
  • 2014-12-09 17:18:56
  • 984

C++ 线程池实现原理

背景多线程编程是C++开发者的一个基本功, 但是很多开发者都是直接使用公司给包装好的线程池库, 没有去了解具体实现,有些实现也都因为高度优化而写得讳莫如深,让初学者看得吃力。所以写这篇文章主要是想以非...
  • yockie
  • yockie
  • 2016-06-07 20:36:14
  • 5519

基于C++11 thread 实现线程池

这里基于C++11 thread实现线程池,线程池不可拷贝。 1 nocopyable类     不可拷贝基类继承它,派生类不可拷贝,实现如下 //nocopyable.h #ifndef NO...
  • u013507368
  • u013507368
  • 2015-08-31 10:39:05
  • 4183
    个人资料
    等级:
    访问量: 2万+
    积分: 582
    排名: 8万+
    最新评论