C++11線程池設(shè)計(jì)與實(shí)現(xiàn)

線程池是一種常見的并發(fā)編程模式,它可以將任務(wù)分配給多個(gè)線程來并行執(zhí)行,從而提高程序的整體性能。C++11標(biāo)準(zhǔn)中引入了std::thread和std::future等線程庫,使得實(shí)現(xiàn)一個(gè)簡單的線程池變得更加便捷。
下面是一個(gè)簡單的C++11線程池設(shè)計(jì)與實(shí)現(xiàn):
1.定義任務(wù)類
需要先定義一個(gè)任務(wù)類,它包含要執(zhí)行的函數(shù)和相關(guān)參數(shù),例如:
class Task {
public:
? ? Task(std::function<void()> func) : m_func(func) {}
? ? void operator()() { m_func(); }
private:
? ? std::function<void()> m_func;
};
2.定義線程池類
線程池類應(yīng)該包含線程池的狀態(tài)信息以及一些控制方法,例如:
class ThreadPool {
public:
? ? ThreadPool(size_t numThreads) {
? ? ? ? for (size_t i = 0; i < numThreads; ++i) {
? ? ? ? ? ? m_threads.emplace_back([this] {
? ? ? ? ? ? ? ? while (true) {
? ? ? ? ? ? ? ? ? ? std::function<void()> task;
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? std::unique_lock<std::mutex> lock(m_mutex);
? ? ? ? ? ? ? ? ? ? ? ? m_condition.wait(lock, [this] {
? ? ? ? ? ? ? ? ? ? ? ? ? ? return m_stop || !m_tasks.empty();
? ? ? ? ? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? ? ? ? ? if (m_stop && m_tasks.empty()) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? task = std::move(m_tasks.front());
? ? ? ? ? ? ? ? ? ? ? ? m_tasks.pop();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? task();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? }
? ? }
? ? ~ThreadPool() {
? ? ? ? {
? ? ? ? ? ? std::unique_lock<std::mutex> lock(m_mutex);
? ? ? ? ? ? m_stop = true;
? ? ? ? }
? ? ? ? m_condition.notify_all();
? ? ? ? for (std::thread& thread : m_threads) {
? ? ? ? ? ? thread.join();
? ? ? ? }
? ? }
? ? template<typename F, typename... Args>
? ? auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
? ? ? ? using return_type = decltype(f(args...));
? ? ? ? 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(m_mutex);
? ? ? ? ? ? if (m_stop) {
? ? ? ? ? ? ? ? throw std::runtime_error("enqueue on stopped ThreadPool");
? ? ? ? ? ? }
? ? ? ? ? ? m_tasks.emplace([task]() { (*task)(); });
? ? ? ? }
? ? ? ? m_condition.notify_one();
? ? ? ? return res;
? ? }
private:
? ? std::vector<std::thread> m_threads;
? ? std::queue<std::function<void()>> m_tasks;
? ? std::mutex m_mutex;
? ? std::condition_variable m_condition;
? ? bool m_stop = false;
};
其中,構(gòu)造函數(shù)初始化了一定數(shù)量的線程,并將每個(gè)線程的執(zhí)行代碼封裝在一個(gè)lambda表達(dá)式中。enqueue方法用于向任務(wù)隊(duì)列中添加任務(wù),并返回一個(gè)future對(duì)象,以便調(diào)用者可以獲取任務(wù)的執(zhí)行結(jié)果。
3.使用線程池
使用線程池很簡單,只需要?jiǎng)?chuàng)建一個(gè)ThreadPool對(duì)象并調(diào)用enqueue方法即可:
ThreadPool pool(4); // 創(chuàng)建包含4個(gè)線程的線程池
auto result1 = pool.enqueue([]{ return 1+2; });
auto result2 = pool.enqueue([]{ return 3+4; });
std::cout << result1.get() << std::endl; // 輸出3
std::cout << result2.get() << std::endl; // 輸出7
以上就是一個(gè)簡單的C++11線程池的設(shè)計(jì)與實(shí)現(xiàn)。需要注意的是,線程池的大小應(yīng)該根據(jù)系統(tǒng)資源和任務(wù)類型來合理設(shè)置,以避免線程過多或線程空閑時(shí)間過長的問題。