线程池的C++实现

本文详细介绍了如何在C++中实现线程池,包括底层原理、优先队列的使用以及高级应用示例,展示了如何创建和管理线程池以提高并发性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇文章用来学习和实现轻松掌握C++线程池:从底层原理到高级应用

代码如下:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <deque>
#include <queue>
#include <atomic>
#include <chrono>

using namespace std;

struct Task {
    Task(int id) : id_(id){};
    void exec() {
        std::cout << "Task " << id_ << " is doing" << std::endl;
    }
private:
    int id_;
};

class ThreadPool {
public:
    ThreadPool(size_t threadCount) : terminate(false), threadCount(threadCount), taskCount(0), completedTaskCount(0)
    {//构造函数,创建线程池,将每个线程添加到vector里。
        for (size_t threadNum = 0; threadNum < threadCount; ++threadNum) {
//成员函数指针,必须在前面加&,普通函数若想表示函数指针,可加&也可以不加。学一下构造thread的几种方法。
            threads.emplace_back(&ThreadPool::threadFunc, this, threadNum);
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
        }
    }

    ~ThreadPool() {
        terminate = true;
        condition.notify_all();
        for (thread& th : threads) {
            if (th.joinable()) {
                th.join();
            }
        }
    }

    void addTask(const Task& task) {
        {
            taskQueue.push(task);//或者用emplace(task)
            taskCount++;
        }
        condition.notify_one();//每往任务队列中加入一个任务,就通知线程池处理一个
    }

    size_t getCompletedTaskCount() const {
        return completedTaskCount.load();
    }

private:
    void threadFunc(int threadNum) {
                std::cout << "threadFunc " << threadNum << " is ready" << "\n";
        while (true) {
            unique_lock<mutex> lock(queueMutex);
//几个线程都在这里排队等待,当外部调用condition.notify_one();时,操作系统一般是调用排队的最前面的线程
//当其它地方发出notify时,它先通过lambda表达式,判断如果return true,就继续执行,否则进入等待状态。
//比如taskQueue不为空,或者terminate为true,就继续往下执行。
            condition.wait(lock, [this]() { return (!taskQueue.empty()) || terminate; });

            if (terminate && taskQueue.empty()) {
                break;
            }

            Task task = taskQueue.front();
            taskQueue.pop();
            task.exec(); //里面内容随便填,表示当前task可以用了
            std::cout << "This task is doing with threadNum " << threadNum << "\n" << "\n";
            ++completedTaskCount;

            //由于这里是死循环,每个线程处理完后,又重新进入循环,排队等待后面的task的到来,相当于做了线程回收
        }
    }

    std::vector<std::thread> threads;

//定义queue队列来存任务,FIFO结构,先存的任务先处理
    std::queue<Task> taskQueue;

//定义互斥锁和条件变量,用于线程池里,等待task到来
    std::mutex queueMutex;
    std::condition_variable condition;

public:
//下面2个变量不需要定义原子操作,直接访问更简洁
    size_t threadCount;
    size_t taskCount;

private:
//下面2个变量定义原子变量,保证线程安全
    atomic<bool> terminate;
    atomic<size_t> completedTaskCount;
};

int main() {
    ThreadPool pool(3);
    std::cout << "ThreadPool pool OK" << "\n\n";

    for (int i = 0; i < 5; ++i) {
        Task task(i);
        pool.addTask(task);
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }

    std::cout << "Thread count: " << pool.threadCount << "\n";
    std::cout << "Task count: " << pool.taskCount << "\n";
    std::cout << "Completed task count: " << pool.getCompletedTaskCount() << "\n\n";
    return 0;
}

执行时要加-pthread,结果是:

$ g++ -pthread 线程池.cpp 
$ ./a.out 
threadFunc 0 is ready
threadFunc 1 is ready
threadFunc 2 is ready
ThreadPool pool OK

Task 0 is doing
This task is doing with threadNum 0

Task 1 is doing
This task is doing with threadNum 1

Task 2 is doing
This task is doing with threadNum 2

Task 3 is doing
This task is doing with threadNum 0

Task 4 is doing
This task is doing with threadNum 1

Thread count: 3
Task count: 5
Completed task count: 5

注:
①代码中的threads.emplace_back不可以替代为thread.push_back。
因为push_back 接受容器的元素类型的对象,并将其拷贝(左值)或移动(右值)到容器的末尾。
而emplace_back接受构造函数的参数,并在容器的末尾直接构造一个新元素,而不需要创建临时对象。
括号里的内容是参数,不是对象。

②原文章中用了优先队列priority,我在这里为了简单,用的是queue。
关于优先队列,task本身没有定义顺序。这里每次队列里有一个任务时就处理了,并未体现出多个任务需要调度时,按优先级高的先进行处理。但这么定义排序的写法是没错的。举个例子:

#include <iostream>
#include <queue>
#include <vector>

// 自定义比较函数 LessByPriority
struct LessByPriority {
    bool operator()(int a, int b) {
        return a < b; // 优先级低的排在前面,如果要优先级高的排在前面,则改为 a < b
    }
};

int main() {
    std::priority_queue<int, std::vector<int>, LessByPriority> pq;

    // 逐个插入元素
    pq.push(5);
    pq.push(7);
    pq.push(2);
    pq.push(9);
    pq.push(3);

    // 输出队列中排好序的结果
    std::cout << "Priority Queue sorted result: ";
    while (!pq.empty()) {
        std::cout << pq.top() << " ";
        pq.pop();
    }
    std::cout << std::endl;

    return 0;
}

结果是:

Priority Queue sorted result: 9 7 5 3 2 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码到程攻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值