下面是实现简单线程池的代码攻略。
什么是线程池?
线程池是一种用于管理多线程执行的机制,允许在需要时提供可分配的工作线程集中的线程。使用线程池的好处是可以减少线程的创建和销毁次数,避免线程频繁创建和销毁所带来的开销,也可以避免同时开启大量的线程造成系统资源的过度占用。在实际生产环境中,线程池通常具有限制线程数量、任务队列、线程管理等功能。
C++实现线程池的示例代码
下面我们以C++为例,使用C++11中的线程库,实现一个简单的线程池。主要的类和函数有:
-
std::thread
:C++11中的线程类,用于创建新线程。 -
std::mutex
:C++11中的互斥量类,用于线程间的互斥访问。 -
std::condition_variable
:C++11中的条件变量类,用于线程间的同步。 -
std::function
:C++11中的函数类,用于存储任意可调用对象,包括函数指针、成员函数指针、lambda表达式等。 -
std::queue
:C++中的队列类,用于存储任务列表。
下面是一个简单的线程池实现代码。该线程池的主要功能包括添加任务、执行任务和关闭线程池。
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <queue>
#include <vector>
class ThreadPool {
public:
ThreadPool(int num_threads) : is_running_(true) {
for (int i = 0; i < num_threads; ++i) {
threads_.emplace_back(std::bind(&ThreadPool::ThreadFunc, this));
}
}
~ThreadPool() {
{
std::unique_lock<std::mutex> lock(queue_mutex_);
is_running_ = false;
}
cv_.notify_all();
for (auto& thread : threads_) {
thread.join();
}
}
void AddTask(std::function<void()> task_func) {
std::unique_lock<std::mutex> lock(queue_mutex_);
tasks_.push(std::move(task_func));
cv_.notify_one();
}
private:
void ThreadFunc() {
while (is_running_) {
std::unique_lock<std::mutex> lock(queue_mutex_);
cv_.wait(lock, [this] { return !tasks_.empty() || !is_running_; });
if (!is_running_) {
break;
}
auto task = std::move(tasks_.front());
tasks_.pop();
lock.unlock();
task();
}
}
bool is_running_;
std::mutex queue_mutex_;
std::condition_variable cv_;
std::queue<std::function<void()>> tasks_;
std::vector<std::thread> threads_;
};
上述代码中,创建线程池时,需要指定线程池的线程数量,然后创建相应数量的工作线程。每个工作线程都执行ThreadFunc()
函数中的操作。ThreadFunc()
函数中不断地查询任务队列,如果队列为空就等待,直到队列中有新的任务进来或者线程池已经被终止。
当添加新任务时,需要将任务函数存储到任务队列中,并唤醒一个等待的线程执行任务。
关闭线程池时,需要将每个工作线程终止,并删除队列中尚未执行的任务。
示例代码说明
这里给出两个简单的示例代码说明:
- 示例1:使用线程池求和
#include <iostream>
#include "ThreadPool.h"
int Sum(int a, int b) {
std::cout << "Thread " << std::this_thread::get_id() << ": Sum a and b\n";
return a + b;
}
void main() {
ThreadPool thread_pool(4);
std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
auto func = [](int n) { return n * n; };
int sum = 0;
for (auto n : numbers) {
thread_pool.AddTask([&sum, n]() { sum += n; });
}
auto result_future = thread_pool.AddTask(std::bind(Sum, 100, 200));
std::cout << "Thread " << std::this_thread::get_id() << ": Submi task for Sum(100, 200)\n";
for (auto n : numbers) {
thread_pool.AddTask(std::bind([&sum](int n) { sum += n; }, func(n)));
}
std::cout << "Thread " << std::this_thread::get_id() << ": Waiting for result\n";
std::cout << "Result: " << sum + result_future.get() << std::endl;
}
上述代码中,首先创建了一个线程池thread_pool
,然后向线程池中添加了多个任务,如对数列中的每个数求平方和,以及调用Sum
函数计算100和200的和。其中,Sum
函数是一个简单的计算两个参数和的函数。
可以看到,添加任务时,可以使用lambda表达式、std::function
、std::bind
等方式来封装任务函数。使用线程池可以减少代码中的线程创建及管理开销。
- 示例2:使用线程池处理图像
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include "ThreadPool.h"
void ProcessImage(cv::Mat& image) {
int channels = image.channels();
int n_rows = image.rows;
int n_cols = image.cols * channels;
for (int i = 0; i < n_rows; ++i) {
uchar* data = image.ptr<uchar>(i);
for (int j = 0; j < n_cols; ++j) {
data[j] = 255 - data[j];
}
}
}
void main() {
cv::Mat image = cv::imread("sample.jpg");
if (image.empty()) {
std::cout << "Cannot read image file" << std::endl;
return;
}
ThreadPool thread_pool(4);
std::vector<cv::Mat> image_parts;
int num_parts = 4;
int part_rows = image.rows / num_parts;
for (int i = 0; i < num_parts; ++i) {
cv::Mat image_part(image, cv::Rect(0, i * part_rows, image.cols, part_rows));
image_parts.push_back(image_part);
}
std::vector<std::future<void>> results;
for (auto& part : image_parts) {
results.push_back(thread_pool.AddTask(std::bind(ProcessImage, std::ref(part))));
}
for (auto& result : results) {
result.get();
}
cv::imwrite("result.jpg", image);
}
这是一个简单的图像处理示例,在使用原始方式处理图像时,需要在循环中遍历图像的每个像素进行处理,这样的操作需要较长的时间。而在使用线程池方式处理图像时,可以将图像分成几个部分,让每个线程单独处理一部分图像,然后等处理完成后合并成完整的图像。这样,可以大大缩短图像处理时间。
在示例代码中,首先读取一张图片sample.jpg
,然后将图片分成4部分,并向线程池中添加图像处理任务。任务处理完成后,等待各个任务执行完毕,将处理后的图像保存为result.jpg
。可以看到,使用线程池处理图像需要创建很少的线程,且线程资源得到高效的利用。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++实现一个简单的线程池的示例代码 - Python技术站