在某些場景下,需要週期性的執行耗時操作,比如寫文件。這種場景,有兩個需求點:
1.執行一次任務比較耗時,不能影響主業務性能。
2.該任務週期性執行。
這種場景:可以每次在執行任務時啓動一個線程,但是這樣做,當任務執行比較頻繁時,需要多次創建線程,這樣會有不小的由於線程多次創建引起的性能損耗。所以,可以採用如下方案:
啓動一個後臺線程,當有任務時,被喚醒,沒有任務時,線程睡眠。
#pragma once
#include <mutex>
#include <condition_variable>
#include <string>
#include <vector>
#include <thread>
#include <iostream>
using namespace std;
class SingleInstance
{
public:
static SingleInstance *getInstance();
static void start(void * arg);
void addMsg(string msg);
private:
SingleInstance();
~ SingleInstance() = default;
private:
static SingleInstance * instance;
static mutex instanceLock;
vector<string> msg;
condition_variable msgCV;
mutex msgLock;
};
實現代碼如下:
#include "SingleInstance.h"
SingleInstance * SingleInstance::instance = nullptr;
mutex SingleInstance::instanceLock;
SingleInstance *SingleInstance::getInstance()
{
if (instance == nullptr) {
lock_guard<mutex> lk(instanceLock);
if (instance == nullptr) {
instance = new SingleInstance();
}
}
return instance;
}
SingleInstance::SingleInstance()
{
thread t(SingleInstance::start,this);
t.detach(); // 作爲後臺線程運行
}
void SingleInstance::start(void *args)
{
SingleInstance * instance = static_cast<SingleInstance *>(args);
if(instance == nullptr){
return;
}
while (1) {
unique_lock<mutex> lk(instance->msgLock);
while (instance->msg.empty())
{
instance->msgCV.wait(lk);
}
cout <<"server receive msg is:"<< instance->msg[0] << endl;
instance->msg.clear();
}
}
void SingleInstance::addMsg(string msg)
{
lock_guard<mutex> lk(this->msgLock);
this->msg.push_back(msg);
this->msgCV.notify_one();
}
測試代碼如下:
#include <iostream>
#include <string>
#include <map>
#include "LogTime.h"
#include "SingleInstance.h"
using namespace std;
int main(int argc, int * argv[])
{
SingleInstance * instance = SingleInstance::getInstance();
instance->addMsg("hello");
for (int i = 0; i < 1e5; i++);
instance->addMsg("world");
system("pause");
}
測試結果如下:
尤其是對於有特殊需求的日誌這種場景,可以採用這種方式。當然,在單條日誌數據量不太的場景下,可以先將日誌寫在緩存裏,當緩存滿了之後,再將日誌發送給sever進行寫文件