What is Thread Pool in C++: Explanation and Example
thread pool in C++ is a collection of pre-created threads that efficiently manage multiple tasks by reusing threads instead of creating new ones each time. It helps improve performance by reducing the overhead of thread creation and destruction.How It Works
Imagine you have a team of workers ready to do tasks. Instead of hiring a new worker for every single job, you keep a fixed team that takes turns doing the work. This is how a thread pool works in C++. It creates a set number of threads at the start and keeps them alive, waiting for tasks.
When a new task comes, the thread pool assigns it to one of the free threads. Once the thread finishes the task, it goes back to the pool to wait for the next job. This way, the program avoids the time and resource cost of creating and destroying threads repeatedly.
This approach is especially useful when you have many small tasks that need to run concurrently, like handling multiple user requests or processing data in parallel.
Example
This example shows a simple thread pool in C++ using the standard library. It creates a pool of threads that execute tasks from a queue.
#include <iostream> #include <vector> #include <thread> #include <queue> #include <functional> #include <condition_variable> #include <mutex> class ThreadPool { public: ThreadPool(size_t numThreads) : stop(false) { for (size_t i = 0; i < numThreads; ++i) { workers.emplace_back([this] { while (true) { std::function<void()> task; { std::unique_lock<std::mutex> lock(this->queueMutex); this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); }); if (this->stop && this->tasks.empty()) return; task = std::move(this->tasks.front()); this->tasks.pop(); } task(); } }); } } template<class F> void enqueue(F&& f) { { std::unique_lock<std::mutex> lock(queueMutex); tasks.emplace(std::forward<F>(f)); } condition.notify_one(); } ~ThreadPool() { { std::unique_lock<std::mutex> lock(queueMutex); stop = true; } condition.notify_all(); for (std::thread &worker : workers) worker.join(); } private: std::vector<std::thread> workers; std::queue<std::function<void()>> tasks; std::mutex queueMutex; std::condition_variable condition; bool stop; }; int main() { ThreadPool pool(3); // 3 threads in the pool for (int i = 1; i <= 5; ++i) { pool.enqueue([i] { std::cout << "Task " << i << " is running on thread " << std::this_thread::get_id() << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(100)); }); } std::this_thread::sleep_for(std::chrono::seconds(1)); // wait for tasks to finish return 0; }
When to Use
Use a thread pool when you have many small or medium tasks that need to run concurrently and you want to avoid the cost of creating and destroying threads repeatedly. It is ideal for server applications handling multiple client requests, parallel data processing, or any program that benefits from running tasks in the background efficiently.
Thread pools help improve performance and resource management by limiting the number of active threads and reusing them, which reduces overhead and prevents your system from creating too many threads that could slow it down.
Key Points
- A thread pool keeps a fixed number of threads ready to run tasks.
- It improves performance by reusing threads instead of creating new ones.
- Tasks are queued and assigned to threads when they become free.
- Useful for handling many concurrent tasks efficiently.
- C++ standard library does not have a built-in thread pool, so you often implement your own or use third-party libraries.