c++ 线程池的两种形式

149 阅读1分钟

c++ 线程池

#include<thread>
#include<mutex>
#include<functional>
#include<condition_variable>
#include<vector>
#include<queue>class ThreadPool {
    std::mutex mtx;
    std::mutex cntMtx;
    std::condition_variable condition;
    std::vector<std::thread> threads;
    std::queue<std::function<void()>> tasks;
    bool stop = false;
    volatile int cnt = 0;
    //volatile 避免被编译器优化掉public:
    ThreadPool(int nums = 8) {
        for (int i = 0; i < nums; i++) {
            threads.emplace_back([this]() -> void {
                while (true) {
                    std::unique_lock<std::mutex> lock(mtx);
                    //获得锁的所有权
                    condition.wait(lock, [this] {return !tasks.empty() || stop; });
                    if (stop && tasks.empty())return;
                    std::function<void()> task = std::move(tasks.front());
                    tasks.pop();
                    lock.unlock();
                    //可以并发执行
                    task();
​
                    lock.lock();
                    cnt--;
                    //
                }
                });
        }
    }
    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(mtx);
            stop = true;
            //{}的作用是创建作用域便于std::unique_lock析构
        }
        condition.notify_all();
        for (auto& thread : threads) {
            thread.join();
        }
    }
​
    void waitEnd() {
        while (true) {
            if (cnt == 0)return;
            //volatile 避免被编译器优化掉
        }
    }
    template<class F, class ...Args>
    void add(F&& f, Args&& ...args) {
        std::function<void()> task(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
        //万能引用和完美转发
        {
            std::unique_lock<std::mutex> lock(mtx);
            tasks.emplace(std::move(task));
            cnt++;
            
        }
        condition.notify_one();
        //唤醒线程执行任务
    }
​
};

如果有并发队列还存在另一种形式

#pragma once
#include <atomic>
#include <thread>
#include <memory>
#include <vector>
#include <functional>
#include <concurrent_queue.h>
//使用Microsoft的concurrent_queueclass ThreadPool {
public:
    ThreadPool(size_t numThreads) : stop(false) {
        for (size_t i = 0; i < numThreads; ++i) {
            workers.emplace_back([this] {
                while (true) {
                    if (stop.load() == true) return;
                    if (tasks.empty())continue;
​
                    std::function<void()>task;
                    while (!tasks.try_pop(task));
                    if (task == nullptr)return;
                  
                    task();
                    cnt--;
                }
                });
        }
    }
​
    ~ThreadPool() {
        stop = true;
        
        for (auto& worker : workers) {
            tasks.push(nullptr); // 使用一个特殊值唤醒所有线程
        }
        for (std::thread& worker : workers) {
            worker.join();
        }
    }
    template<class F, class ...Args>
    void add(F&& f, Args&& ...args) {
        std::function<void()> task(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...)
        );
        tasks.push(std::move(task));
        cnt++;
    }
    void wait() volatile {
        while (true) {
            int cur_cnt = cnt.load();
            if (cur_cnt == 0)return;
        }
    }
private:
    Concurrency::concurrent_queue<std::function<void()>> tasks;
    std::vector<std::thread> workers;
    std::atomic<bool> stop;
    std::atomic<int> cnt;
};

对于性能暂未测试