c++11/14线程池

c++11

// #pragma once
#include <iostream>
#include <thread>
#include <memory>
#include <vector>
#include <queue>
#include <functional>               // std:;function
#include <future>                   // std::packaged_task
#include <condition_variable>
#include <algorithm>
#include <mutex>
#include <atomic>
using namespace std;


class ThreadPool{
public:
    using Ptr = std::shared_ptr<ThreadPool>;
public:
    static Ptr GetInstance(const int& num_threads=8){
        auto pThread = std::shared_ptr<ThreadPool>(new ThreadPool(num_threads));
        return pThread;
    }

    ~ThreadPool(){
        if(_is_running){
            wait();
            stop();
        }

    }
    void wait(){
        std::unique_lock<mutex> lock(_task_mtx);
        while(_running_task_num > 0 || _task_pool.size()>0){
            _finished_cv.wait(lock);
        }
    }

    void stop(){
        _is_running = false;
        _running_cv.notify_all();
        for(auto& t:_thread_pool){
            if(t.joinable()) t.join();
        }
        // _finished_cv.notify_all();      // ?不需要
    }
    template<typename FuncT, typename... ParamT>
    auto submit(FuncT&& f, ParamT&&... params)->std::future<typename std::result_of<FuncT(ParamT...)>::type>
    {
        using returnType = typename std::result_of<FuncT(ParamT...)>::type;
        auto task = std::make_shared<std::packaged_task<returnType()>>(
            std::bind(std::forward<FuncT>(f), std::forward<ParamT>(params)...)
        );
        {
            std::unique_lock<mutex> lock(_task_mtx);
            _task_pool.emplace([task](){(*task)();});
        }
        _running_cv.notify_one();
        return task->get_future();
    }

private:
    ThreadPool(const int& num_threads)
        :_thread_num(min(num_threads, (int)std::thread::hardware_concurrency())), _is_running(true), _running_task_num(0)
    {
        for(int i=0;i<_thread_num;i++){
            _thread_pool.emplace_back(
                [this](){
                    std::function<void()> task;
                    while(true){
                        {
                            std::unique_lock<mutex> lock(_task_mtx);
                            while(_is_running && _task_pool.empty()) _running_cv.wait(lock);
                            if((!_is_running)  && _task_pool.empty()) break;
                            task = std::move(_task_pool.front());
                            _task_pool.pop();
                            _running_task_num++;
                        }
                        task();
                        _running_task_num--;
                        _finished_cv.notify_all();  // 唤醒一个?
                    }
                }
            );
        }

    }

    int _thread_num;
    vector<std::thread> _thread_pool;
    queue<std::function<void()>> _task_pool;
    atomic<int> _running_task_num;
    atomic<bool> _is_running;
    std::condition_variable _running_cv;
    std::condition_variable _finished_cv;
    std::mutex _task_mtx;

};

// g++ -std=c++11 ThreadPool_c11.cpp -o ThreadPool_c11
int main(){
    std::cout <<"std::thread::hardware_concurrency():"<<std::thread::hardware_concurrency() << std::endl;
    int size = 5;
    vector<int> nums(size);
    for(int i=0; i<size; i++){
        nums[i] = i;
    }
    auto func = [](int& i){
        int tmp = i;
        i = i*i;
        std::cout<<"thread id:"<<std::this_thread::get_id() << " " << tmp << "^2: "<< i <<std::endl;
    };
    auto p = ThreadPool::GetInstance(10);

    for(auto& n:nums){
        p->submit(func, ref(n));
    }
    p->wait();
    // std::this_thread::sleep_for(std::chrono::seconds(1));
    for(auto& n:nums){
        cout <<"n:" << n<<" ";
    }
    cout <<endl;
}


c++14

// threadpool.cpp
#include <iostream>
#include <thread>
#include <queue>
#include <atomic>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <future>
#include <memory>
#include <functional>
using namespace std;


class ThreadPool{
private:
    int __thread_num;
    atomic<bool> __is_run;
    atomic<int> __run_num;
    vector<std::thread> __thread_pool;
    queue<std::function<void()>> __task_pool;
    
    condition_variable  __cv_run;
    condition_variable __cv_finish;
    mutex __task_mtx;

public:
    ThreadPool(const int& threadnum);
    ~ThreadPool();

    void wait();
    void stop();
    template<typename funT, typename... ParamT>
    auto submit(funT&& f, ParamT&&... param);
};

ThreadPool::ThreadPool(const int& threadnum):__thread_num(threadnum), __is_run(true), __run_num(0)
{
    for(int i=0; i< __thread_num; i++){
        __thread_pool.emplace_back(
            [this](){
                std::function<void()> task;
                while(true){
                    {   
                        unique_lock<mutex> lock(__task_mtx);
                        __cv_run.wait(lock, [this](){return !(__is_run && __task_pool.empty());});
                        if(!__is_run && __task_pool.empty()) break; 
                        task = std::move(__task_pool.front());
                        __task_pool.pop();
                        ++__run_num;
                    }
                    task();
                    --__run_num;
                    __cv_finish.notify_one();
                }
            }
        );
    }
}
ThreadPool::~ThreadPool(){
    if(__is_run){
        wait();
        stop();
    }
}
void ThreadPool::wait(){
    unique_lock<mutex> lock(__task_mtx);
    __cv_finish.wait(lock, [this](){ return !(__run_num>0 || !__task_pool.empty());});
}

void ThreadPool::stop(){
    __is_run = false;
    __cv_run.notify_all();
    for(auto& th : __thread_pool){
        if(th.joinable()) th.join();
    }
}

template<typename funT, typename... ParamT>
auto ThreadPool::submit(funT&& f, ParamT&&... param){
    auto task = std::make_shared<std::packaged_task<decltype(f(param...))()>>(
        std::bind(std::forward<funT>(f), std::forward<ParamT>(param)...)
    );
    {
        unique_lock<mutex> lock(__task_mtx);
        __task_pool.emplace([task](){
            (*task)();
        });
    }
    __cv_run.notify_one();
    return task->get_future();
}


void sqr(int& value){
    value *= value;
    cout<<"thread id:"<<std::this_thread::get_id() << " value:"<<value <<endl;
}
// g++ -std=c++14 threadpool.cpp -o threadpool
int main(){
    vector<int> nums;
    for(int i=0; i<10;i++) nums.push_back(i);

    auto p = new ThreadPool(10);

    
    for(auto& num:nums){
        p->submit(sqr, ref(num));
    }
    p->wait();
    for(auto& num:nums){
        cout <<"num:"<< num<<" ";
    }
    cout<<endl;

    delete p;
}

posted @ 2023-04-26 17:38  小小灰迪  阅读(20)  评论(0编辑  收藏  举报