在项目中经常会遇到一些需要异步处理的(耗时长)并且线程不安全的对象在多线程模型中使用,封装了一个实用的线程模板,用于直接处理这类的事务。将该线程不安全的对象直接绑定到单个线程上,然后将一个外部处理函数压入队列,由该线程取出对象和处理函数调用。绑定的对象作为第一个参数传入处理函数中,其余入参依次传入函数的实参。
代码如下, 版本:c++14, 编译器:gcc 5.4
#include <thread>
#include <iostream>
#include <functional>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <chrono>
template<typename INSTANCE>
class SafeThread
{
public:
SafeThread(std::shared_ptr<INSTANCE> i) : instance(i)
{
worker = std::thread([this] {
while(!this->stop)
{
std::function<void()> task;
{
std::unique_lock<std::mutex> lck(this->queue_mtx);
this->condition.wait(lck, [this] { return this->stop || !this->tasks.empty();} );
if (this->stop)
{
break;
}
else if (this->tasks.empty())
{
throw std::runtime_error("consume an empty task");
}
task = std::move(this->tasks.front());
this->tasks.pop();
}
task();
}
});
}
virtual ~SafeThread()
{
stop = true;
std::unique_lock<std::mutex> lck(queue_mtx);
condition.notify_all();
worker.join();
}
template<typename F, typename... Args>
void Insert(F f, Args... args)
{
auto task = std::bind(std::forward<F>(f), instance, std::forward<Args>(args)...);
std::unique_lock<std::mutex> lck(queue_mtx);
if (stop)
{
throw std::runtime_error("insert into a stopped thread");
}
tasks.emplace(task);
condition.notify_one();
}
private:
std::shared_ptr<INSTANCE> instance;
std::thread worker;
std::queue<std::function<void()>> tasks;
std::mutex queue_mtx;
std::condition_variable condition;
bool stop = false;
};
// a non-thread-safe class
class UnSafe
{
public:
void add(int x, int y)
{
while(y -- > 0)
{
counts += x;
}
}
void print()
{
std::cout << "counts : " << counts << std::endl;
}
int counts = 0;
};
using namespace std::chrono_literals;
int main()
{
int cnts = 10000;
const int interval = 5;
const int times = 10;
auto us = std::make_shared<UnSafe>();
while(cnts -- > 0)
{
std::thread([&us] () {
us->add(interval, times);
}).detach();
}
std::this_thread::sleep_for(3s);
us->print();
cnts = 10000;
us->counts = 0;
SafeThread<UnSafe> st(us);
while(cnts -- > 0)
{
std::thread([&st] () {
st.Insert([] (std::shared_ptr<UnSafe> _us, int _interval, int _times) {
_us->add(_interval, _times);
}, interval, times);
}).detach();
}
std::this_thread::sleep_for(3s);
us->print();
std::string end = "";
while(std::cin >> end)
{
if (tolower(end.at(0)) == 'q')
{
break;
}
}
}
执行结果:
来源:CSDN
作者:飞雪翔羽
链接:https://blog.csdn.net/github_36099226/article/details/103705887