说明
该版本添加了停止线程池的方法,使用了智能指针,并且可以异步获取返回值
线程池类头文件
x_thread_pool.h
#pragma once
#include <thread>
#include <mutex>
#include <vector>
#include <list>
#include <functional>
#include <atomic>
#include <future>
class XTask
{
public:
virtual int Run() = 0; // 任务的入口函数
std::function<bool()> is_exit = nullptr;
auto GetReturn()
{
// 阻塞等待
return p_.get_future().get();
}
void SetValue(int v)
{
p_.set_value(v);
}
private:
// 用来接收返回值
std::promise<int> p_;
};
class XThreadPool
{
public:
// 初始化线程池
// num 为线程的数量
void Init(int num);
// 启动所有线程,调用前必须先调用Init
void Start();
// 线程池退出
void Stop();
// 插入任务
void AddTask(std::shared_ptr<XTask> task);
// 获取任务
std::shared_ptr<XTask> GetTask();
// 线程池是否退出
bool is_exit()
{
return is_exit_;
}
int task_run_count()
{
return task_run_count_;
}
private:
// 线程池线程的入口函数
void Run();
int thread_num_ = 0; // 线程数量
std::mutex mux_;
std::vector<std::shared_ptr<std::thread>> threads_;
std::list<std::shared_ptr<XTask>> tasks_;
std::condition_variable cv_;
bool is_exit_ = false; // 线程池退出
std::atomic<int> task_run_count_ = {0}; // 正在运行的函数数量
};
实现文件
x_thread_pool.cpp
#include "x_thread_pool.h"
#include <iostream>
using namespace std;
void XThreadPool::Init(int num)
{
unique_lock<mutex> lock(mux_);
this->thread_num_ = num;
cout << "Thread pool init " << num << "\n";
}
// 启动所有线程,必须先调用Init
void XThreadPool::Start()
{
unique_lock<mutex> lock(mux_);
if (thread_num_ <= 0)
{
cerr << "Please Init XThreadPool" << "\n";
}
if (!threads_.empty())
{
cerr << "Thread pool has start!" << "\n";
}
// 启动线程
for (int i = 0; i < thread_num_; i++)
{
auto th = make_shared<thread>(&XThreadPool::Run, this);
threads_.push_back(th);
}
}
void XThreadPool::Stop()
{
is_exit_ = true;
cv_.notify_all();
for (auto& th: threads_)
{
th->join();
}
unique_lock<mutex> lock(mux_);
threads_.clear();
}
void XThreadPool::Run()
{
cout << "begin XThreadPool Run" << this_thread::get_id() << '\n';
while(!is_exit())
{
auto task = GetTask();
++task_run_count_; // 运行一个任务时候数量加1
if (!task) continue;
try
{
auto re = task->Run();
task->SetValue(re);
} catch (...)
{
}
--task_run_count_;
}
cout << "exit XThreadPool Run" << this_thread::get_id() << '\n';
}
void XThreadPool::AddTask(std::shared_ptr<XTask> task)
{
unique_lock<mutex> lock(mux_);
tasks_.push_back(task);
task->is_exit = [this]
{
return is_exit();
};
lock.unlock();
cv_.notify_one();
}
std::shared_ptr<XTask> XThreadPool::GetTask()
{
unique_lock<mutex> lock(mux_);
if (tasks_.empty())
{
cv_.wait(lock);
}
if (is_exit()) return nullptr;
if (tasks_.empty())
{
return nullptr;
}
auto task = tasks_.front();
tasks_.pop_front();
return task;
}
入口文件
#include <iostream>
#include "x_thread_pool.h"
using namespace std;
class MyTask:public XTask
{
public:
int Run() override
{
std::cout << "MyTask" << name << '\n';
for (int i = 0; i < 10; i++)
{
if (is_exit()) break;
cout << "." << flush;
this_thread::sleep_for(500ms);
}
return 111;
}
std::string name = "";
};
int main()
{
XThreadPool pool;
pool.Init(16);
pool.Start();
auto task1 = make_shared<MyTask>();
task1->name = "test name 001";
pool.AddTask(task1);
auto re = task1->GetReturn();
cout << "task1 return: " << re << '\n'; // 等待运行结束获取返回结果
this_thread::sleep_for(1s);
pool.Stop();
getchar();
return 0;
}