/*** 线程池实现过程 ***/
/* 创建Task类表示任务 */
class Task {
public:
/* 使用bind将函数和参数绑定,将返回的函数指针传给Task的成员func */
/* Task的构造函数为模板方法 */
template<typename FUNC_T, typename ...ARGS>
Task(FUNC_T func, ARGS... args) {
this->func = bind(func, forward<ARGS>(args)...);
}
void run() {
this->func();
return ;
}
/* 使用function<void()>函数指针来接受bind的返回值 */
function<void()> func;
};
/* 创建ThreadPool类 */
class ThreadPool {
public:
ThreadPool(int n = 1) : thread_size(n), starting(false), threads(n) {
this->start();
return ;
}
/* worker函数可以想象成流水线上的工人, 不停地取任务和执行任务 */
void worker() {
/* this_thread::get_id() 可以返回 当前线程的id */
auto id = this_thread::get_id();
running[id] = true;
while (running[id] == true) {
Task *t = get_task(); // 取任务
t->run(); // 执行任务
delete t;
}
return ;
}
void start() {
if (starting == true) return ;
/* 创建thread_size个线程 */
for (int i = 0; i < thread_size; i++) {
/* 可以想象成是把工人放进流水线让他们工作 */
threads[i] = new thread(&ThreadPool::worker, this);
}
starting = true;
return ;
}
/* 此方法是将任务添加到任务队列 */
template<typename FUNC_T, typename ...ARGS>
void add_task(FUNC_T func, ARGS... args) {
/* 加锁访问公共资源 */
unique_lock<mutex> lock(m_mutex);
tasks.push(new Task(func, forward<ARGS>(args)...));
/* 通知有任务进入队列 */
m_cond.notify_one();
return ;
}
/* 此方法是将所有线程停止并清空 */
void stop() {
if (starting == false) return ;
/* 添加threads.size()个停止任务,使所有接到该任务的线程停止 */
for (int i = 0; i < threads.size(); i++) {
this->add_task(&ThreadPool::stop_running, this);
}
/* 等待所有线程结束 */
for (int i = 0; i < threads.size(); i++) {
threads[i]->join();
}
/* 清空所有线程 */
for (int i = 0; i < threads.size(); i++) {
delete threads[i];
threads[i] = nullptr;
}
starting = false;
return ;
}
/* ThreadPool的析构函数 */
~ThreadPool() {
/* 将所有线程停止并清空 */
this->stop();
/* 将任务队列清空 */
while (!tasks.empty()) {
delete tasks.front();
tasks.pop();
}
return ;
}
/* ThreadPool的成员属性 */
private:
/* 停止任务,作用是使接到该任务的线程停止 */
void stop_running() {
auto id = this_thread::get_id();
running[id] = false;
return ;
}
/* 该函数为工人取任务的方法 */
Task *get_task() {
/* 加锁访问公共资源 */
unique_lock<mutex> lock(m_mutex);
/* 如果任务队列为空则进入等待 */
while (tasks.empty()) m_cond.wait(lock);
Task *t = tasks.front();
tasks.pop();
return t;
}
int thread_size; // 表示线程个数
bool starting; // 表示整个线程池是否启动
std::mutex m_mutex; // 互斥锁
std::condition_variable m_cond; // 条件信号量
vector<thread *> threads; // 使用vector存储线程指针
unordered_map<std::thread::id, bool> running; // 使用unordered_map来表示线程是否在运行
queue<Task *> tasks; // 任务队列
};
/****** 使用样例 ******/
/*** 统计5000万以内的素数个数 ***/
bool is_prime(int x) {
for (int i = 2; i * i <= x; i++) {
if (x % i == 0) return false;
}
return true;
}
int prime_count(int l, int r) {
int ans = 0;
for (int i = l; i <= r; i++) {
ans += is_prime(i);
}
return ans;
}
void work(int l, int r, int &ret) {
cout << this_thread::get_id() << " begin" << endl;
ret = prime_count(l, r);
cout << this_thread::get_id() << " done" << endl;
return ;
}
int main() {
ThreadPool tp(5);
#define batch 5000000
int ret[10];
for (int i = 0, j = 1; i < 10; i++, j += batch) {
tp.add_task(work, j, j + batch - 1, ref(ret[i]));
}
tp.stop();
int ans = 0;
for (auto x : ret) ans += x;
cout << ans << endl;
return 0;
}
线程池(C++代码演示)
于 2024-02-23 18:44:48 首次发布