先看用法:
添加了4个任务,全都首次不执行,
任务1周期性执行,间隔500ms
任务2只执行一次
任务3只执行一次
任务4周期性执行,间隔3000ms。
void TestTask1() {
std::cout << "Task 1 executed" << std::endl;
}
void TestTask2() {
std::this_thread::sleep_for(100ms);
std::cout << "Task 2 executed" << std::endl;
}
void TestTask3() {
std::this_thread::sleep_for(200ms);
std::cout << "Task 3 executed" << std::endl;
}
void TestTask4() {
std::this_thread::sleep_for(300ms);
std::cout << "Task 4 executed" << std::endl;
}
int main() {
TaskManager task_mgr;
task_mgr.Start();
auto task_id1 = task_mgr.AddTask(Task(500ms, TestTask1, false));
auto task_id2 = task_mgr.AddTask(Task(1000ms, TestTask2, false, false));
auto task_id3 = task_mgr.AddTask(Task(2000ms, TestTask3, false, false));
auto task_id4 = task_mgr.AddTask(Task(3000ms, TestTask4, false));
std::this_thread::sleep_for(5000ms);
task_mgr.RemoveTask(task_id2);
task_mgr.RemoveTask(task_id3);
std::this_thread::sleep_for(8000ms);
task_mgr.Stop();
return 0;
}
以下是实现:
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <chrono>
#include <condition_variable>
#include <functional>
#include <iostream>
#include <map>
#include <mutex>
#include <queue>
#include <thread>
#include <vector>
using namespace std::chrono_literals;
class Task {
public:
Task(std::chrono::milliseconds interval, std::function<void()> func,
bool run_for_first_time = true, bool repeat = true)
: id_(boost::uuids::random_generator()()),
interval_(interval),
func_(std::move(func)),
repeat_(repeat) {
next_run_time_ = run_for_first_time
? std::chrono::steady_clock::now()
: std::chrono::steady_clock::now() + interval_;
}
const boost::uuids::uuid& GetId() const {
return id_; }
void Run() {
func_();
if (repeat_) {
// 计算出下一次执行时间点
next_run_time_ += interval_;
// 由于func本身的执行会消耗时间,我们需要判断是否超出了一个执行周期
auto now = std::chrono::steady_clock::now();
auto diff = now - next_run_time_;
if (diff > std::chrono::milliseconds::zero()) {
// 如果差值已经超过了一个周期,则直接将下一次执行时间推迟一个周期
next_run_time_ += std::chrono::duration_cast<std::chrono::milliseconds>(
std::ceil(diff.count() / static_cast<double>(interval_.count())) *
interval_);
}
}
}
bool Repeat() const {
return repeat_; }
std::chrono::steady_clock::time_point GetNextRunTime() const {
return next_run_time_;
}
// 提供给优先级队列做比较使用, 优先级队列会把大的数放到前面,
// next_run_time_的值较大的, 说明不需要立刻执行, 应看成比较小。
bool operator<(const Task& other) const {
return next_run_time_ > other.next_run_time_;
}
private:
boost::uuids::uuid id_;
std::chrono::milliseconds interval_;
std::function<void()> func_;
bool repeat_;
std::chrono::steady_clock::time_point next_run_time_;
};
class TaskManager {
public:
explicit TaskManager(int thread_count = 1) : exit_(false) {
SetThreadCount(thread_count);
task_queue_.resize(thread_count_);
for (int i = 0; i < thread_count_; ++i) {
queue_mutex_.push_back(std::make_unique<std::mutex>());
}
for (int i = 0; i < thread_count_; ++i) {
cv_.push_back(std::make_unique<std::condition_variable>());
}
}
boost::uuids::uuid AddTask(Task task) {
{
std::lock_guard<std::mutex> lock(mutex_);
tasks_.insert(std::make_pair(task.GetId(), task));
}
{
auto index = *task.GetId().begin() % thread_count_;
std::lock_guard<std::mutex> lock(*queue_mutex_[index]);
task_queue_[index].push(task);
cv_[index]->notify_all();
}
return task.GetId();
}
void RemoveTask(const boost::uuids::uuid& task_id) {
{
std::lock_guard<std::mutex> lock(mutex_);
tasks_.erase(task_id);
}
}
bool Contains(const boost::uuids::uuid& task_id) {
{
std::lock_guard<std::mutex> lock(mutex_);
return tasks_.count(task_id) > 0;
}
}
void Start() {
for (int i = 0; i < thread_count_; ++i) {
threads_.emplace_back([&]() {
while (!exit_) {
std::unique_lock<std::mutex> lock(*queue_mutex_[i]);
while (!task_queue_[i].empty() &&
task_queue_[i].top().GetNextRunTime() <=
std::chrono::steady_clock::now()) {
auto task = task_queue_[i].top();
task_queue_[i].pop();
if (Contains(task.GetId())) {
// 判断是否还在tasks_中,因为任务可能被人取消了,取消就不执行了
task.Run();
if (task.Repeat()) {
// 需要重复执行则归还到优先级队列
task_queue_[i].push(task);
} else {
RemoveTask(task.GetId()); // 不需要重复执行则从tasks_中删除,不需要从queue中删除,因为下次取出自然会删除
}
}
}
if (!exit_) {
auto wait_time = task_queue_[i].empty()
? 10ms
: (task_queue_[i].top().GetNextRunTime() -
std::chrono::steady_clock::now());
// 等待的时间是根据下一个需要执行的任务精确计算出来的,如果没有任务要执行,那就睡10ms
cv_[i]->wait_for(lock, wait_time);
}
}
});
}
}
void Stop() {
exit_ = true;
for (int i = 0; i < thread_count_; ++i) {
cv_[i]->notify_all();
}
for (auto& thread : threads_) {
thread.join();
}
}
private:
void SetThreadCount(int count) {
thread_count_ = std::min(static_cast<unsigned int>(std::max(count, 1)),
std::thread::hardware_concurrency());
}
private:
std::map<boost::uuids::uuid, Task> tasks_;
std::vector<std::priority_queue<Task>> task_queue_;
std::vector<std::unique_ptr<std::mutex>> queue_mutex_;
std::mutex mutex_;
std::vector<std::unique_ptr<std::condition_variable>> cv_;
bool exit_;
int thread_count_{
1};
std::vector<std::thread> threads_;
};
void TestTask1() {
std::cout << "Task 1 executed" << std::endl; }
void TestTask2() {
// std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "Task 2 executed" << std::endl;
}
void TestTask3() {
// std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::cout << "Task 3 executed" << std::endl;
}
void TestTask4() {
// std::this_thread::sleep_for(std::chrono::milliseconds(300));
std::cout << "Task 4 executed" << std::endl;
}
int main() {
TaskManager task_mgr;
task_mgr.Start();
auto task_id1 = task_mgr.AddTask(Task(500ms, TestTask1, false));
auto task_id2 = task_mgr.AddTask(Task(1000ms, TestTask2, false, false));
auto task_id3 = task_mgr.AddTask(Task(2000ms, TestTask3, false, false));
auto task_id4 = task_mgr.AddTask(Task(3000ms, TestTask4, false));
std::this_thread::sleep_for(5000ms);
task_mgr.RemoveTask(task_id2);
task_mgr.RemoveTask(task_id3);
std::this_thread::sleep_for(8000ms);
task_mgr.Stop();
return 0;
}
待优化空间: