为什么要用线程池(C++)?

1)不用线程池时:

void handle_request()
{
    std::thread t([]{
        // 干活
    });
    t.detach();
}
问题很明显:

  • ❌ 频繁 new thread / destroy thread,开销大
  • ❌ 线程数量不可控,可能把系统拖死
  • ❌ 不好统一管理、退出、回收

线程池的本质一句话:

线程提前创建好,反复用;任务丢进去,线程自己取。

二、线程池的核心模型(一定要理解)

线程池 ≈ 三样东西

+--------------------+
|   Task Queue       |  <- function<void()>
+--------------------+
        ▲
         |
+--------------------+
|   Worker Threads   |  多个 while(true)
+--------------------+
        ▲
         |
+--------------------+
|  PushBack / Submit |
+--------------------+

三、一个最小但完整的线程池

1️⃣ 定义线程池类

ThreadPool.h 头文件:

#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <vector>
#include <thread>
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>

class ThreadPool
{
public:
    using Task = std::function<void()>;

    explicit ThreadPool(size_t n);
    ~ThreadPool();

    void Push(Task task);

private:
    std::vector<std::thread> m_workers;
    std::queue<Task> m_tasks;

    std::mutex m_mutex;
    std::condition_variable m_cond;
    bool m_stop;
};

#endif

#include "ThreadPool.h"

ThreadPool::ThreadPool(size_t n)
    : m_stop(false)
{
    for (size_t i = 0; i < n; ++i)
    {
        m_workers.emplace_back([this] {
            while (true)
            {
                Task task;
                {
                    std::unique_lock<std::mutex> lock(m_mutex);
                    m_cond.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.cpp 文件:

ThreadPool::~ThreadPool()
{
    {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_stop = true;
    }
    m_cond.notify_all();

    for (auto& t : m_workers)
        t.join();
}

void ThreadPool::Push(Task task)
{
    {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_tasks.push(std::move(task));
    }
    m_cond.notify_one();
}


四、最基础的用法示例

int main()
{
    ThreadPool pool(3);  // 3 个工作线程

    for (int i = 0; i < 10; ++i)
    {
        pool.Push([i] {
            printf("task %d running in thread %ld\n",
                   i, std::this_thread::get_id());
            std::this_thread::sleep_for(std::chrono::seconds(1));
        });
    }

    getchar();
    return 0;
}

五:Makefile的编写:

CXX := g++
CXXFLAGS := -std=c++11 -Wall -O2 -pthread

TARGET := threadpool_demo

SRCS := \
                main.cpp \
                        ThreadPool.cpp

OBJS := $(SRCS:.cpp=.o)

all: $(TARGET)

$(TARGET): $(OBJS)
                $(CXX) $(CXXFLAGS) -o $@ $^

%.o: %.cpp
                $(CXX) $(CXXFLAGS) -c $< -o $@

clean:
                rm -f $(OBJS) $(TARGET)

.PHONY: all clean

执行结果如下: ./threadpool_demo 
task 0 running in thread 140640437704448
task 1 running in thread 140640446097152
task 2 running in thread 140640429311744
task 3 running in thread 140640437704448
task 4 running in thread 140640446097152
task 5 running in thread 140640429311744
task 6 running in thread 140640446097152
task 8 running in thread 140640429311744
task 7 running in thread 140640437704448
task 9 running in thread 140640446097152

Could not load content