目录
1. 概述
线程池技术绝不是C++独有的,Java和Python都有比较晚完善的线程池构造接口。
通俗的讲,线程池只是一种管理线程的方式。很多时候,我们为了充分利用CPU和Memory资源,会创建一些独立的线程,执行同步或异步的任务。但有一个不得不考虑的问题是,现成的创建和销毁本身也是消耗系统资源的,尤其是一些需要频繁创建和销毁线程的应用场景下。当然有时候有一些连续的任务也不需要通过线程池技术来完成。
如上所述,为了避免频繁创建和销毁线程带来的系统资源的消耗,我们可以提前创建一定数量的线程,用来等待和处理队列中的事务,无需反复地创建和销毁线程。
2. 例程
(1)ThreadPool.h
#ifndef __THREADPOOL_H__
#define __THREADPOOL_H__
#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
class ThreadPool
{
public:
ThreadPool(size_t threads);
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type>
{
using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared<std::packaged_task<return_type()>>(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> lock(queueMutex);
if (stop) {
throw std::runtime_error("enqueue on stopped ThreadPool");
}
tasks.emplace([task]() { (*task)(); });
}
condition.notify_one();
return res;
}
~ThreadPool();
private:
std::vector<std::thread> workers;
std::queue<std::function<void()>> tasks;
std::mutex queueMutex;
std::condition_variable condition;
bool stop;
};
#endif ///< __THREADPOOL_H__
(2)ThreadPool.cpp
#include "ThreadPool.h"
ThreadPool::ThreadPool(size_t threads) : stop(false)
{
for (size_t i = 0; i < threads; ++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();
}
});
}
}
ThreadPool::~ThreadPool()
{
{
std::unique_lock<std::mutex> lock(queueMutex);
stop = true;
}
condition.notify_all();
for (std::thread &worker : workers) {
worker.join();
}
}
(3)Start.cpp
#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "ThreadPool.h"
/** sudo g++ -std=c++17 -o ./Start.bin ./*.cpp -lpthread */
#define EXTERNAL_FUNC 0 ///< 0: 类内部成员
///< 1: 类外部成员
#if EXTERNAL_FUNC == 1
// 定义一个返回整数的函数
int intFunction(int x)
{
return x * x;
}
// 定义一个返回字符串的函数
std::string stringFunction(std::string s)
{
return s + " world";
}
int main(int argc, char* argv[])
{
ThreadPool pool(4);
// 使用enqueue来执行intFunction,传入参数4
auto result1 = pool.enqueue(intFunction, 4);
// 使用enqueue来执行stringFunction,传入参数"hello"
auto result2 = pool.enqueue(stringFunction, "hello");
// 获取并打印结果
std::cout << "result1: " << result1.get() << std::endl; // 应该打印出16
std::cout << "result2: " << result2.get() << std::endl; // 应该打印出"hello world"
return 0;
}
#else ///< 作为类成员
class DemoClass
{
public:
DemoClass(int num_threads = 1)
{
if(num_threads <= 0 ){
num_threads = 1;
}
pool = new ThreadPool(num_threads);
}
~DemoClass()
{
delete pool;
pool = nullptr;
}
void printTask(int n)
{
std::cout << "Processing " << n << std::endl;
}
void startProcessing()
{
for (int i = 1; i <= 50; ++i){
pool->enqueue(&DemoClass::printTask, this, i);
usleep(1); ///< 短暂的等待是有必要的.
}
}
private:
ThreadPool* pool = nullptr;
};
int main(int argc, char* argv[])
{
DemoClass myClass(10);
myClass.startProcessing();
return 0;
}
#endif
(4)编译
sudo g++ -std=c++17 -o ./Start.bin ./*.cpp -lpthread