自学内容网 自学内容网

C++11实现线程库

本篇博客通过packaged_task 封装一个可以让用户拿到线程结果的线程池。
packaged_task 可以封装模板类,可以封装一个函数,模板类型是该函数的返回值类型,可以通过get_future 获得future来获得函数的返回值。该线程池最终的一个函数就是想线程池中push任务的函数,用户可以自己要执行的函数以及参数传递进来,然后线城池启动线程进行执行,通过函数返回值的方式让用户拿到数据。因为用户要执行的参数个数类型是不确定的,所以该函数是一个模板函数,第一个模板参数是要执行的函数,第二个是可变参数模板,用来接收用户的参数,在函数内部通过绑定参数,来得到一个无参的可执行对象,通过构造lambda的方式来添加进入任务队列。具体代码如下:

#pragma once
#include <iostream>
#include <future>
#include <vector>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <memory>

class ThreadPool
{
    using Functor = std::function<void()>;
public:
    ThreadPool(int threadnum = 5) : _stop(false)
    {
        for(int i = 0; i < threadnum; ++i)
        {
            _threads.emplace_back(std::thread(&ThreadPool::entry, this));
        }
    }

    // 对任务进行封装packaged_task,使用lambda传入任务池
    template<typename F, typename ...Args>
    auto push(F&& f, Args&& ...args) -> std::future<decltype(f(args...))>
    {
        // 获取返回值类型
        using return_type = decltype(f(args...));
        // 把参数进行绑定
        auto fun = std::bind(&std::forward<F>(f), std::forward<Args>(args)...);
        // 封装成为packaged_task 指针, 一定要构建堆上的对象
        auto pack_task_ptr = std::make_shared<std::packaged_task<return_type()>>(fun);
        // 获取返回值
        std::future<return_type> res = pack_task_ptr->get_future();
        // 加锁
        {
            std::unique_lock<std::mutex> lock(_mutex);
            // 封装成为lambda 加入到任务池
             _funcs.emplace_back([pack_task_ptr](){ (*pack_task_ptr)(); });
        }
// 唤醒所有线程
        _con.notify_all();
        return res;
    }

    void stop()
    {
        _stop = true;
        _con.notify_all();
        for(auto& th : _threads)
        {
            th.join();
        }
    }

    ~ThreadPool()
    {
        stop();
    }
private:
    // 线程的入口函数
    void entry() 
    {
        while(!_stop)
        {
        // 临时变量,一次拿到所有的任务,一下全部执行,避免频繁的加锁解锁
            std::vector<Functor> tmp;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                // while(!_stop && _funcs.empty())_con.wait(lock);
                _con.wait(lock, [this](){ return _stop || !_funcs.empty();});

                tmp.swap(_funcs);
            }

            for(auto task : tmp)
            {
                task();
            }
        }
    }
private:
    std::atomic<bool> _stop; // 表示线城池是否停止了
    std::mutex _mutex; //互斥锁
    std::condition_variable _con; // 条件变量 
    std::vector<Functor> _funcs;  // 任务池
    std::vector<std::thread> _threads; // 管理的线程
};

原文地址:https://blog.csdn.net/bushibrnxiaohaij/article/details/143840023

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!