C++线程池

#include <thread>
#include <iostream>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <functional>
#include <queue>
#include <memory>
#include <chrono>

// 使用标准命名空间
using namespace std;

// 定义一个常量,用于控制一次增加或减少的线程数量
constexpr int NUMBER = 10;

// 定义任务类,封装了任务函数和参数
class Task {
public:
    // 定义任务函数类型,使用 std::function 提供更大的灵活性
    using TaskFunction = std::function<void(void*)>;

    // 构造函数,接受任务函数和参数
    Task(TaskFunction func, void* arg) : function(func), arg(arg) {}

    // 执行任务
    void execute() {
        if (function) {
            function(arg);
        }
    }

    // 获取任务参数
    void* getArg() const { return arg; }

private:
    TaskFunction function; // 任务函数
    void* arg;             // 任务参数
};

// 线程池类,管理多个工作线程
class ThreadPool {
public:
    // 构造函数,初始化线程池
    ThreadPool(int min, int max, int queueSize)
        : minNum(min), maxNum(max), queueCapacity(queueSize), shutdown(false), exitNum(0) {
        liveNum = minNum; // 设置初始存活线程数为最小线程数

        // 创建初始的工作线程
        for (int i = 0; i < minNum; ++i) {
            threads.emplace_back(&ThreadPool::worker, this);
        }

        // 创建管理线程
        managerThread = std::thread(&ThreadPool::manager, this);
    }

    // 析构函数,销毁线程池
    ~ThreadPool() {
        destroy();
    }

    // 禁用拷贝构造和拷贝赋值
    ThreadPool(const ThreadPool&) = delete;
    ThreadPool& operator=(const ThreadPool&) = delete;

    // 添加任务到线程池
    void addTask(Task::TaskFunction func, void* arg) {
        std::unique_lock<std::mutex> lock(mutexPool);
        // 如果队列满了且未关闭,则等待
        notFull.wait(lock, [this]() { return queue.size() < queueCapacity || shutdown; });

        // 如果线程池已经关闭,则不添加任务
        if (shutdown) return;

        // 将新任务添加到任务队列中
        queue.emplace(new Task(func, arg));
        notEmpty.notify_one(); // 通知工作线程有新任务
    }

    // 获取当前忙碌线程数量
    int busyNum() {
        std::lock_guard<std::mutex> lock(mutexBusy);
        return busyThreadNum;
    }

    // 获取当前存活线程数量
    int aliveNum() {
        std::lock_guard<std::mutex> lock(mutexPool);
        return liveNum;
    }

private:
    // 工作线程函数,处理任务队列中的任务
    void worker() {
        while (true) {
            std::unique_ptr<Task> task;
            {
                std::unique_lock<std::mutex> lock(mutexPool);
                // 如果任务队列为空且未关闭,则等待
                notEmpty.wait(lock, [this]() { return !queue.empty() || shutdown || exitNum > 0; });

                // 如果线程池已关闭且任务队列为空,或者有退出请求,则退出线程
                if ((shutdown && queue.empty()) || (exitNum > 0 && liveNum > minNum)) {
                    if (exitNum > 0 && liveNum > minNum) {
                        exitNum--;
                        liveNum--;
                        break; // 退出线程
                    }
                    if (shutdown) {
                        break; // 退出线程
                    }
                }

                // 如果任务队列不为空,则取出任务
                if (!queue.empty()) {
                    task = std::move(queue.front());
                    queue.pop();
                    notFull.notify_one(); // 通知可以添加新任务
                } else {
                    continue; // 没有任务,继续等待
                }
            }

            // 增加忙碌线程计数
            {
                std::lock_guard<std::mutex> lock(mutexBusy);
                busyThreadNum++;
            }

            // 执行任务,并处理可能的异常
            try {
                task->execute();
            } catch (const std::exception& e) {
                cerr << "Exception in task: " << e.what() << endl;
            } catch (...) {
                cerr << "Unknown exception in task." << endl;
            }

            // 任务执行完毕,减少忙碌线程计数
            {
                std::lock_guard<std::mutex> lock(mutexBusy);
                busyThreadNum--;
            }

            // 释放任务参数内存,避免内存泄漏
            delete static_cast<int*>(task->getArg());
        }
    }

    // 管理线程函数,动态调整线程数量
    void manager() {
        while (!shutdown) {
            // 每隔3秒检测一次线程池状态
            std::this_thread::sleep_for(std::chrono::seconds(3));

            std::lock_guard<std::mutex> lock(mutexPool);

            // 获取当前任务队列大小和忙碌线程数
            int queueSize = queue.size();
            int currentLiveNum = liveNum;
            int currentBusyNum = busyNum();

            // 如果任务数量多于存活线程数且存活线程数小于最大线程数,增加线程
            if (queueSize > currentLiveNum && liveNum < maxNum) {
                int addNum = 0;
                for (int i = 0; i < NUMBER && liveNum < maxNum; ++i) {
                    threads.emplace_back(&ThreadPool::worker, this);
                    liveNum++;
                    addNum++;
                }
                if (addNum > 0) {
                    cout << "Manager: Added " << addNum << " threads. Total live threads: " << liveNum << endl;
                }
            }

            // 如果忙碌线程数少于存活线程数的一半且存活线程数大于最小线程数,减少线程
            if (currentBusyNum * 2 < liveNum && liveNum > minNum) {
                int reduceNum = 0;
                exitNum = NUMBER;
                for (int i = 0; i < NUMBER; ++i) {
                    notEmpty.notify_one(); // 通知空闲线程退出
                    reduceNum++;
                }
                cout << "Manager: Requested to reduce " << reduceNum << " threads. Total live threads: " << liveNum << endl;
            }
        }
    }

    // 销毁线程池
    void destroy() {
        {
            std::lock_guard<std::mutex> lock(mutexPool);
            shutdown = true; // 设置关闭标志
        }
        notEmpty.notify_all(); // 唤醒所有工作线程
        notFull.notify_all();  // 唤醒所有等待添加任务的线程

        if (managerThread.joinable()) {
            managerThread.join();  // 等待管理线程结束
        }

        for (auto& thread : threads) {
            if (thread.joinable()) {
                thread.join(); // 等待所有工作线程结束
            }
        }

        // 清空线程容器
        threads.clear();
    }

    vector<std::thread> threads;               // 存放工作线程
    std::thread managerThread;                 // 管理线程
    std::queue<std::unique_ptr<Task>> queue;   // 任务队列

    int minNum;        // 最小线程数
    int maxNum;        // 最大线程数
    int queueCapacity; // 任务队列容量
    int liveNum;       // 当前存活线程数
    int exitNum;       // 标记需要退出的线程数
    std::atomic<int> busyThreadNum; // 当前忙碌线程数

    std::mutex mutexPool;        // 保护线程池的互斥锁
    std::mutex mutexBusy;        // 保护忙碌线程计数的互斥锁
    std::condition_variable notFull;  // 任务队列不满条件变量
    std::condition_variable notEmpty; // 任务队列不空条件变量
    bool shutdown;               // 是否关闭线程池的标志
};

// 示例任务函数
void taskFunc(void* arg) {
    int num = *(int*)arg;
    cout << "Thread " << this_thread::get_id() << " is working, number = " << num << endl;
    this_thread::sleep_for(std::chrono::seconds(1)); // 模拟任务耗时
}

int main() {
    ThreadPool pool(3, 10, 100); // 创建线程池,最小3个线程,最大10个线程,任务队列容量100

    // 向线程池添加100个任务
    for (int i = 0; i < 100; ++i) {
        int* num = new int(i + 100); // 分配任务参数
        pool.addTask(taskFunc, num);
    }

    // 运行30秒,等待任务处理
    this_thread::sleep_for(std::chrono::seconds(30));

    // 线程池在析构时自动销毁
    return 0;
}
  • Task:封装了任务函数和参数,并提供执行任务的方法。
  • ThreadPool:负责管理工作线程和任务队列,提供添加任务和动态调整线程数量的功能。
  • worker函数:工作线程的核心逻辑,从任务队列中获取任务并执行。
  • manager函数:管理线程的逻辑,根据任务数量动态调整工作线程的数量。
  • 线程池的创建与销毁:构造函数初始化线程池,析构函数确保资源的释放和线程的正常退出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值