c++線程池實現(四)線程池實現

前面已經說到了同步隊列的實現,下面來看線程池的實現。

#ifndef INCLUDE_THREADPOOL__
#define INCLUDE_THREADPOOL__

#include <list>
#include <thread>
#include <memory>
#include <atomic>

#include "SyncQueue.hpp"

namespace MyThreadPool {

class ThreadPool {
    using Task = std::function<void()>;
 public:
    ThreadPool(int max_size = std::thread::hardware_concurrency())
        : sync_queue_{max_size} {
        running_ = true;
        for (int i = 0; i < max_size; ++i) {
            threads_.emplace_back(
                std::make_shared<std::thread>(&ThreadPool::Run, this));
        }
    }

    ~ThreadPool() {
        Stop();
    }

    void AddTask(Task&&task) {
        sync_queue_.Push(std::forward<Task>(task));
    }

 private:
    void Run() {
        while (running_) {
            Task task{[]{}};
            sync_queue_.Pop(task);
            task();
        }
    }

    void Stop() {
        sync_queue_.Clear();
        running_ = false;
        for (int i = 0; i < threads_.size(); ++i) {
            AddTask([]{});
        }
        for (auto &thread : threads_) {
            if (thread && thread->joinable()) {
                thread->join();
            } 
        }
        threads_.clear();
    }

    std::list<std::shared_ptr<std::thread>> threads_;
    std::atomic_bool running_;
    SyncQueue<Task> sync_queue_;
};

}

#endif  // INCLUDE_THREADPOOL__

可以看到,ThreadPool構造的時候就預先創建了一些線程,線程數量默認爲cpu核數。線程會從同步隊列中取出任務,然後執行。同步隊列爲空的話,線程將會處於等待狀態。通過AddTask接口,上層可以將任務添加到同步隊列中,這個時候就喚醒等待獲取任務的隊列。

下面是一個sample:

#include "SyncQueue.hpp"
#include "ThreadPool.hpp"

#include <thread>
#include <iostream>

void task1() {
    std::cout << "task1 start" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(3));
    std::cout << "task1 finish" << std::endl;
}

void task2() {
    std::cout << "task2 start" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(5));
    std::cout << "task2 finish" << std::endl;
}

void task3() {
    std::cout << "task3 start" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(8));
    std::cout << "task3 finish" << std::endl;
}

int main() {
    MyThreadPool::ThreadPool thread_pool(3);
    thread_pool.AddTask(task1);
    thread_pool.AddTask(task2);
    thread_pool.AddTask(task3);

    std::this_thread::sleep_for(std::chrono::seconds(1));

    return 0;
}

可以看到main函數最後添加了一個休眠,主要是爲了確保在線程啓動之前,主線程不會退出。

其實這裏添加的任務還是比較簡單的,實際的情況會複雜一些,例如要求任務會有輸出值,還會有返回值,這樣目前確實不滿足。但是我們可以稍微修改一下AddTask函數,結合std::future,在任務結束後獲取返回值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章