C/C++线程池

介绍

在多线程编程中,线程池是一种常用的技术,可以提高程序的性能和效率。线程池是指预先创建一组线程,并将任务分配给这些线程来执行。通过重用线程,避免了线程创建和销毁的开销,从而提高了程序的响应速度。

本文将介绍C/C++中线程池的概念、实现方法和使用场景,并给出一个简单的代码示例。

线程池的概念

线程池由两个主要组件组成:工作线程和任务队列。

工作线程是预先创建的线程,它们等待任务的到来并执行任务。线程池中的工作线程数量一般是固定的,可以根据实际需求调整。

任务队列是一个存储任务的数据结构,工作线程从任务队列中取出任务并执行。当任务队列为空时,工作线程会等待,直到有任务到达。

线程池的实现方法

任务队列

任务队列是线程池中的核心组件,它负责存储任务并提供任务的添加和获取接口。

任务队列可以使用各种数据结构来实现,例如队列、链表等。在C/C++中,可以使用STL的queue来实现任务队列。

下面是使用queue实现任务队列的示例代码:

#include <queue>
#include <mutex>
#include <condition_variable>

template<typename T>
class TaskQueue {
public:
    void AddTask(T task) {
        std::lock_guard<std::mutex> lock(mutex_);
        queue_.push(task);
        condition_.notify_one();
    }

    T GetTask() {
        std::unique_lock<std::mutex> lock(mutex_);
        condition_.wait(lock, [this] { return !queue_.empty(); });
        T task = queue_.front();
        queue_.pop();
        return task;
    }

private:
    std::queue<T> queue_;
    std::mutex mutex_;
    std::condition_variable condition_;
};

工作线程

工作线程是线程池中的执行单元,它等待任务的到来并执行任务。

工作线程可以使用C/C++标准库提供的线程库来创建和管理。在C++11之后,可以使用std::thread来创建线程。

下面是使用std::thread创建工作线程的示例代码:

#include <iostream>
#include <thread>

void WorkerThread() {
    while (true) {
        // 从任务队列中获取任务
        task = taskQueue.GetTask();
        // 执行任务
        task();
    }
}

int main() {
    // 创建工作线程
    std::thread workerThread(WorkerThread);
    
    // 等待工作线程执行完成
    workerThread.join();

    return 0;
}

线程池

线程池是线程队列和任务队列的组合,它负责管理线程和任务的执行。

线程池可以通过将任务添加到任务队列中,并由工作线程从任务队列中获取任务来实现任务的并发执行。

下面是使用线程池执行任务的示例代码:

#include <vector>
#include <functional>

class ThreadPool {
public:
    ThreadPool(int numThreads) {
        for (int i = 0; i < numThreads; ++i) {
            threads_.push_back(std::thread([this] { WorkerThread(); }));
        }
    }

    ~ThreadPool() {
        for (auto& thread : threads_) {
            if (thread.joinable()) {
                thread.join();
            }
        }
    }

    void AddTask(std::function<void()> task) {
        taskQueue_.AddTask(task);
    }

private:
    void WorkerThread() {
        while (true) {
            // 从任务队列中获取任务
            std::function<void()> task = taskQueue_.GetTask();
            // 执行任务
            task();
        }
    }

private:
    std::vector<std::thread> threads_;
    TaskQueue<std::function<void()>> taskQueue_;
};

使用场景

线程池适用于以下场景:

  • 需要并发执行多个任务,并且任务之间没有严格的依赖关系。
  • 需要控制并发线程的数量,以避免线程创建和销毁的开销。