网站建设与开发试题与答案,建网站引流做淘宝,温州网站建设方案外包,网站建设公司的服务公司目录
线程池:
日志类:
可变参数以及相关函数
1.va_list
2. va_start
3. va_end
日志Log类
线程池 线程池: 是一种线程使用模式。线程过多会带来调度开销#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程#xff0c;等待着 监督管理者分配可并发执行…目录
线程池:
日志类:
可变参数以及相关函数
1.va_list
2. va_start
3. va_end
日志Log类
线程池 线程池: 是一种线程使用模式。线程过多会带来调度开销进而影响缓存局部性和整体性能。而线程池维护着多个线程等待着 监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量
日志类:
在代码中 我对可变参数进行了处理,以下是对可变参数的补充
可变参数以及相关函数 可变参数包含在#include stdarg.h这个库中 1.va_list
va_list是一种类型用于存储可变参数的状态。它通常声明在函数内部表示一个参数列表。
2. va_start va_start宏用于初始化一个va_list对象使其指向可变参数列表的第一个参数。它需要两个参数一个是va_list对象另一个是紧接在可变参数列表之前的最后一个已知参数的名字。
3. va_end
va_end宏用于清理由va_start初始化的va_list对象。在处理完可变参数后必须调用va_end。
例子:
#include stdarg.h
#include stdio.h// 定义一个接受可变参数的函数
void printNumbers(int num, ...) {va_list args; // 声明va_list类型的变量va_start(args, num); // 初始化va_list变量使其指向第一个可变参数for (int i 0; i num; i) {int value va_arg(args, int); // 获取下一个参数类型为intprintf(%d , value);}va_end(args); // 清理va_list变量printf(\n);
}int main() {printNumbers(3, 10, 20, 30); // 调用函数传递三个参数printNumbers(5, 1, 2, 3, 4, 5); // 调用函数传递五个参数return 0;
}日志Log类
#pragma once
#include iostream
#include fstream
#include cstdio
#include string
#include ctime
#include cstdarg
#include sys/types.h
#include unistd.h
#include LockGuard.hpp
bool gIsSave false;
std::string logname log.txt;
pthread_mutex_t lock PTHREAD_MUTEX_INITIALIZER;// 1. 日志是由等级的
enum Level
{DEBUG 0,INFO,WARNING,ERROR,FATAL
};std::string LevelToString(int level)
{switch (level){case DEBUG:return DEBUG;case INFO:return INFO;case WARNING:return WARNING;case ERROR:return ERROR;case FATAL:return FATAL;default:return UNKOWN;}
}void Savefile(std::string filename, std::string message)
{std::ofstream out(filename, std::ios::app);if (!out.is_open()){return;}out message;out.close();
}std::string Gettime()
{time_t currtime time(nullptr);struct tm *fromatetime localtime(currtime);if (fromatetime nullptr){return ERROR;}char buffer[1024];snprintf(buffer, sizeof(buffer), %d-%d-%d-%d-%d-%d,fromatetime-tm_year 1900,fromatetime-tm_mon 1,fromatetime-tm_mday,fromatetime-tm_hour,fromatetime-tm_min,fromatetime-tm_sec);return buffer;
}void Logmessage(int level, int line, std::string filename, const char *format, ...)
{std::string clevel LevelToString(level);std::string time Gettime();pid_t selfpid getpid();va_list arg;char buffer[1024];va_start(arg, format);//可变参数处理vsnprintf(buffer, sizeof(buffer), format, arg);va_end(arg);std::string message [ time ] [ clevel ] [ std::to_string(selfpid) ] [ filename ] [ std::to_string(line) ] buffer \n;LookGuard Lookguard(lock);if (!gIsSave){std::coutmessagestd::endl;}else{Savefile(logname, message);}
}#define LOG(level,format,...) do{Logmessage(level,__LINE__,__FILE__,format,##__VA_ARGS__);}while(0)//c99新增处理可变参数 ##支持没有可变参数时 代码块整体替换 do while(0)
#define EnableFile() do{gIsSavetrue;}while(0)
#define Enablescreem() do{gIsSavefalse;}while(0)
我基于Linux下pthread.h对线程相关的接口进行了封装
#pragma once
#include iostream
#include string
#include unistd.h
#include functional
#include pthread.husing func_t std::functionvoid(std::string);
class Thread
{
public:void Excute(){_func(_threadname);}public:Thread(func_t func, std::string name none-name): _func(func), _threadname(name), _stop(true){}static void *threadroutine(void *args) // 类成员函数形参是有this指针的{Thread *self static_castThread *(args);self-Excute();return nullptr;}bool Start(){int n pthread_create(_tid, nullptr, threadroutine, this);if (!n){_stop false;return true;}else{return false;}}void Detach(){if (!_stop){pthread_detach(_tid);}}void Join(){if (!_stop){pthread_join(_tid, nullptr);}}std::string name(){return _threadname;}void Stop(){_stop true;}~Thread() {}private:pthread_t _tid;std::string _threadname;func_t _func;bool _stop;
};再进行封装之后,便可以进行线程池的搭建了
线程池
#pragma once
#include memory
#include vector
#include queue
#include ctime
#include log.hpp
#include thread.hpp
const static int gthreadnum 5;template typename T
class threadpool
{private:void QueueLock(){pthread_mutex_lock(_mutex);}void QueueUnlock(){pthread_mutex_unlock(_mutex);}void WakeThread(){pthread_cond_signal(_cond);}void WakeAllThread(){pthread_cond_broadcast(_cond);}void Threadsleep(){pthread_cond_wait(_cond, _mutex);}public:threadpool(int threadnum gthreadnum): _threadnum(threadnum), _waitnum(0), _Isrunning(false),_Startnum(0){pthread_mutex_init(_mutex, nullptr);pthread_cond_init(_cond, nullptr);}~threadpool(){pthread_mutex_destroy(_mutex);pthread_cond_destroy(_cond);}void HandlerTask(std::string name){while (true){QueueLock();while (_taskqueue.empty() _Isrunning) // 空的但是还在跑{_waitnum;Threadsleep(); // 去阻塞等待_waitnum--;}if (_taskqueue.empty() !_Isrunning) // 空的而且没跑了{QueueUnlock();std::cout name :quit std::endl;break;}// 2.2 如果线程池不退出 任务队列不是空的// 2.3 如果线程池已经退出 任务队列不是空的 --- 处理完所有的任务然后在退出// 3. 一定有任务, 处理任务T t _taskqueue.front();_taskqueue.pop();if(t()){std::coutmission successstd::endl;} // 执行else{std::coutmission failstd::endl;}QueueUnlock();}}bool Enqueue(const T x){bool ret false;QueueLock();if (_Isrunning){_Startnum;LOG(INFO,%s,ENqueue mission);_taskqueue.push(x);if (_waitnum 0){WakeThread();}ret true;}QueueUnlock();return ret;}void InitThreadPool(){for (int num 0; num _threadnum; num){std::string name Thread: std::to_string(num 1);_threadpool.emplace_back(std::bind(threadpool::HandlerTask, this, std::placeholders::_1), name); // bind绑定类成员函数时,第二个参数必须是this}LOG(INFO,%s,InitPool);_Isrunning true;}bool ReadyToStart(){LOG(INFO,%s,ReadToStart);return _Startnum_threadnum;}void Stop(){QueueLock();_Isrunning false;WakeAllThread(); // 不跑了 把剩的任务跑了 唤醒在_cond下等待的所有线程 并执行LOG(WARNING,%s,STOP);QueueUnlock();}void Wait(){for (auto thread : _threadpool){LOG(INFO,%s:-%s,thread.name().c_str(),wait);thread.Join();}}void Start(){for (auto thread : _threadpool){LOG(INFO,%s:-%s,thread.name().c_str(),start);thread.Start();}}private:int _threadnum;std::vectorThread _threadpool;std::queueT _taskqueue;pthread_mutex_t _mutex;pthread_cond_t _cond;int _waitnum;bool _Isrunning;int _Startnum;
};