当前位置: 首页 > news >正文

网站模板无忧asp.net 网站开发项目化教程

网站模板无忧,asp.net 网站开发项目化教程,网站设置地图,wordpress 获取当前自定义分类线程池介绍 那究竟什么是线程池呢#xff1f; 线程池是一种线程使用模式. 线程过多会带来调度开销#xff0c;进而影响缓存局部性和整体性能. 而线程池维护着多个线程#xff0c;等待着监督管理者分配可并发执行的任务. 这避免了在处理短时间任务时创建与销毁线程的代价. 线…线程池介绍 那究竟什么是线程池呢 线程池是一种线程使用模式. 线程过多会带来调度开销进而影响缓存局部性和整体性能. 而线程池维护着多个线程等待着监督管理者分配可并发执行的任务. 这避免了在处理短时间任务时创建与销毁线程的代价. 线程池不仅能够保证内核的充分利用还能防止过分调度. 前面我们介绍过生产者消费者模型线程池其实看作是它的一个变型 它把任务队列和消费者(线程)进行了封装统称为server 用户不需要再关心线程创建的问题只需要构建好任务把它直接送往server里面即可server会帮我们解决对应的任务 具体的应用场景有哪些呢 需要大量的线程来完成任务且完成任务的时间比较短. WEB服务器完成网页请求这样的任务使用线程池技术是非常合适的.因为单个任务小而任务数量巨大你可以想象一个热门网站的点击次数. 对性能要求苛刻的应用比如要求服务器迅速响应客户请求。 接受突发性的大量请求但不至于使服务器因此产生大量线程的应用。突发性大量客户请求在没有线程池情况下将产生大量线程虽然理论上大部分操作系统线程数目最大值不是问题短时间内产生大量线程可能使内存到达极限从而出现错误 第一个版本(基本框架搭建) 了解基本概念后我们就可以具体实现相应的代码 本质上就是创建一个类 不过该类里面会自动封装相应的锁条件变量以及对应创建销毁线程的方法 一旦实例化就有相应的线程为我们服务用户不需要再考虑线程创建的问题而只需要传任务即可 具体代码如下 任务队列我们依旧用queue进行实现并且不对任务的上限做约束 线程数目我们先设定为5个如果有需求再进行对应的调整即可 1 #pragma once2 #include iostream3 #include vector4 #include queue5 #include Task.hpp6 #include pthread.h7 8 const static int N 5; //默认线程数量9 template class T10 class ThreadPool11 {12 public:13 ThreadPool(int num N):_num(num),_threads(num)14 {15 pthread_mutex_init(_mutex,nullptr);16 pthread_cond_init(_cond,nullptr);17 }18 ~ThreadPool()19 {20 pthread_mutex_destroy(_mutex);21 pthread_cond_destroy(_cond);22 }23 void LockQueue()24 {25 pthread_mutex_lock(_mutex); //给任务队列上锁26 }27 void UnlockQueue()28 {29 pthread_mutex_unlock(_mutex); //给任务队列解锁30 } 31 void ThreadWait()32 {33 pthread_cond_wait(_cond,_mutex); //没有任务线程自动进入等待34 }35 void ThreadWakeUp()36 {37 pthread_cond_signal(_cond); //唤醒任务队列里面的线程38 }39 //判断任务队列是否为空 40 bool Isempty()41 {42 return _tasks.empty();43 }44 T popTask()45 {46 T t _tasks.front();47 _tasks.pop();48 return t;49 }50 void PushTask(const Tt)51 {52 LockQueue(); //给任务队列加锁53 _tasks.push(t); //任务入列54 ThreadWakeUp(); //唤醒线程进行工作55 UnlockQueue(); //任务队列解锁56 }57 static void* ThreadRoutine(void* args)58 {59 //每个线程自己挂接这样自动销毁60 pthread_detach(pthread_self());61 //将传进啦的this指针转成我们的对象这样即可访问里面的方法和成员变量62 ThreadPoolTask* tp static_castThreadPoolTask *(args);63 while (true)64 {65 tp-LockQueue(); //每个线程访问任务队列时都必须先加锁66 //任务队列不为空67 while(tp-Isempty())68 {69 tp-ThreadWait(); //假如没有任务则等待 70 }71 //有任务取出对应的任务72 T t tp-popTask();73 //归还锁让其它线程也能够拿到74 tp-UnlockQueue();75 t(); //执行任务76 std::cout ThreadRoutine done: t.formatRes() std::endl;77 }78 }79 //创建对应的线程80 void start()81 { 82 //创建对应的线程83 for(int i 0;i _num;i)84 {85 pthread_create(_threads[i],nullptr,ThreadRoutine,(void*)this);86 }87 }88 private:89 std::vectorpthread_t _threads; //线程编号向量90 int _num; //线程数量91 92 std::queueT _tasks; //任务数量93 pthread_mutex_t _mutex; //锁94 pthread_cond_t _cond; //条件变量95 }; 第二个版本(封装自己的线程) 在第一个版本中我们采用的是原生线程库里面的线程进行的封装 但我们还可以进一步进行改造用我们之前自己封装的线程来实现线程池. //自己封装的线程 #include iostream #include stdlib.h #include pthread.h #include cstring #include string class Thread{ public:typedef enum{NEW 0,RUNNING,EXITED}ThreadStatus;typedef void* (*func_t)(void*); public:Thread(int num,func_t func,void* args):_tid(0),_status(NEW),_func(func),_args(args){//名字由于还要接收用户给的编号因此在构造函数内进行初始化char buffer[128];snprintf(buffer,sizeof(buffer),thread-%d,num);_name buffer;}~Thread(){}//返回线程的状态int status() {return _status;}//返回线程的名字std::string name() {return _name;}//返回线程的id//只有线程在运行的时候才会有对应的线程idpthread_t GetTid(){if (_status RUNNING){return _tid;}else{return 0;}}//pthread_create函数默认第三个参数是void *(*start_routine) (void *)//而类成员函数具有默认参数this指针直接传并不匹配所以我们用static修饰使其变成类成员函数//但是会有新的问题——无法访问类内成员也就无法调用_funcstatic void * ThreadRun(void* args){Thread* ts (Thread*)args; //此时就获取到我们对象的指针// _func(args); //无法回调相应的方法(成员变量无法直接被访问)(*ts)(); //传this指针进来用仿函数回调_funcreturn nullptr;}void operator()() //仿函数{//假如传进来的线程函数不为空则调用相应的函数if(_func ! nullptr) _func(_args);}//线程运行void Run(){//线程创建的参数有四个int n pthread_create(_tid,nullptr,ThreadRun,this);if(n ! 0) exit(0);_status RUNNING;}//线程等待void Join(){int n pthread_join(_tid,nullptr);if (n ! 0){std::cerr main thread join error : _name std::endl;return;}_status EXITED;} private:pthread_t _tid; //线程idstd::string _name; //线程的名字func_t _func; //未来要回调的函数void*_args;ThreadStatus _status; //目前该线程的状态 };//V2版本 #pragma once #include iostream #include vector #include queue #include Task.hpp #include pthread.hconst static int N 5; //默认线程数量 template class T class ThreadPool { public:ThreadPool(int num N):_num(num),_threads(num){pthread_mutex_init(_mutex,nullptr);pthread_cond_init(_cond,nullptr);}~ThreadPool(){pthread_mutex_destroy(_mutex);pthread_cond_destroy(_cond);}void LockQueue(){pthread_mutex_lock(_mutex); //给任务队列上锁}void UnlockQueue(){pthread_mutex_unlock(_mutex); //给任务队列解锁}void ThreadWait(){pthread_cond_wait(_cond,_mutex); //没有任务线程自动进入等待}void ThreadWakeUp(){pthread_cond_signal(_cond); //唤醒任务队列里面的线程}//判断任务队列是否为空bool Isempty(){return _tasks.empty();}T popTask(){T t _tasks.front();_tasks.pop();return t;}void PushTask(const Tt){LockQueue(); //给任务队列加锁_tasks.push(t); //任务入列ThreadWakeUp(); //唤醒线程进行工作UnlockQueue(); //任务队列解锁}static void* ThreadRoutine(void* args){//每个线程自己挂接这样自动销毁pthread_detach(pthread_self());//将传进啦的this指针转成我们的对象这样即可访问里面的方法和成员变量ThreadPoolTask* tp static_castThreadPoolTask *(args);while (true){tp-LockQueue(); //每个线程访问任务队列时都必须先加锁//任务队列不为空while(tp-Isempty()){tp-ThreadWait(); //假如没有任务则等待}//有任务取出对应的任务T t tp-popTask();//归还锁让其它线程也能够拿到tp-UnlockQueue();t(); //执行任务std::cout ThreadRoutine done: t.formatRes() std::endl;}}//创建对应的线程void start(){ //创建对应的线程for(int i 0;i _num;i){pthread_create(_threads[i],nullptr,ThreadRoutine,(void*)this);}} private:std::vectorpthread_t _threads; //线程编号向量int _num; //线程数量std::queueT _tasks; //任务数量pthread_mutex_t _mutex; //锁pthread_cond_t _cond; //条件变量 };第三个版本(封装自己的锁) 在第二个版本中我们用自己封装的线程来实现线程池. 再进一步改造我们还可以用我们自己封装的锁来进一步进行封装. //自己封装的锁 #pragma once#include iostream #include pthread.hclass Mutex { public:Mutex(pthread_mutex_t* mutex):pmutex(mutex){}~Mutex(){}void Lock(){pthread_mutex_lock(pmutex);}void Unlock(){pthread_mutex_unlock(pmutex);} private:pthread_mutex_t* pmutex; };class LockGuard { public:LockGuard(pthread_mutex_t* mutex):_mutex(mutex){//在创建的时候就自动上锁_mutex.Lock();}~LockGuard(){//销毁的时候自动解锁_mutex.Unlock();}private:Mutex _mutex; };我们自己实现的锁会在创建时自动上锁出了作用域后自动进行解锁 因此我们原来线程池代码可以进一步进行优化 给任务队列进行上锁解锁的成员函数都可以直接删除 假如要上锁只需要创建对应LockGuard对象即可然后把临界区的代码用中括号全部括起来 #pragma once #include iostream #include vector #include queue #include Task.hpp #include pthread.h #include Thread.hpp #include mymutex.hppconst static int N 5; //默认线程数量 template class T class ThreadPool { public:ThreadPool(int num N):_num(num){pthread_mutex_init(_mutex,nullptr);pthread_cond_init(_cond,nullptr);}~ThreadPool(){for(auto t:_threads){t.Join();}pthread_mutex_destroy(_mutex);pthread_cond_destroy(_cond);}pthread_mutex_t* Getlock(){return _mutex;}void ThreadWait(){pthread_cond_wait(_cond,_mutex); //没有任务线程自动进入等待}void ThreadWakeUp(){pthread_cond_signal(_cond); //唤醒任务队列里面的线程}//判断任务队列是否为空bool Isempty(){return _tasks.empty();}T popTask(){T t _tasks.front();_tasks.pop();return t;}void PushTask(const Tt){LockGuard lockguard(_mutex);_tasks.push(t); //任务入列ThreadWakeUp(); //唤醒线程进行工作}static void* ThreadRoutine(void* args){//将传进啦的this指针转成我们的对象这样即可访问里面的方法和成员变量ThreadPoolTask* tp static_castThreadPoolTask *(args);while (true){T t;//任务队列不为空{LockGuard lockguard(tp-Getlock());while(tp-Isempty()){tp-ThreadWait(); //假如没有任务则等待}//有任务取出对应的任务t tp-popTask();}t(); //执行任务std::cout Routine done: t.formatRes() std::endl;}}//创建对应的线程void Init(){for(int i 0;i _num;i){_threads.push_back(Thread(i,ThreadRoutine,(void*)this));} }void start(){for (auto t:_threads){ t.Run(); //调用自定义线程里面的Run函数创建相应的线程}}void Check(){for(auto t:_threads){std::cout t.name() is Running... std::endl;}} private:std::vectorThread _threads; //线程编号向量int _num; //线程数量std::queueT _tasks; //任务数量pthread_mutex_t _mutex; //锁pthread_cond_t _cond; //条件变量 }; 我们可以用我们实现的线程池完成加减乘除的任务 首先实现一个Task类该类会用传入其中的x,y,运算符创建对象 调用对应的仿函数即可完成对应的四则运算任务 #pragma once #include iostream #include stringclass Task { public://无参构造Task(){}Task(int x,int y,char op):_x(x),_y(y),_op(op),_result(0),_exitflag(0){}~Task(){}void operator()(){switch(_op){case :{_result _x _y;break;}case -:{_result _x - _y;break;}case *:{_result _x * _y;break;}case /:{if(_y 0)_exitflag -1;else_result _x / _y;break;}case %:{ if (_y 0)_exitflag -2;else_result _x % _y;break;}default:break;}}std::string formatArgs(){return std::to_string(_x) _op std::to_string(_y) ; }std::string formatRes(){return std::to_string(_result) ( std::to_string(_exitflag) );} private:int _x;int _y;char _op; //运算符int _result; //运算的结果int _exitflag; //退出成功与否 };主函数传参时把对应构建好的Task类对象传入即可剩下的工作线程池会自动帮我们创建好对应的线程执行并显示我们的任务 #include iostream #include Task.hpp #include unistd.h #include memory //#include ThreadPool_V1.hpp //#include ThreadPool_V2.hpp #include ThreadPool_V3.hpp int main() {ThreadPoolTask* tp new ThreadPoolTask();tp-Init();tp-start(); //线程池启动tp-Check(); //看线程是否启动成功while(true){int x,y;char op;std::cout Please enter x:;std::cin x;std::cout Please enter y:;std::cin y;std::cout Please enter op(-*/%):;std::cin op;Task t(x,y,op);tp-PushTask(t); //将任务传入线程池中即可}return 0; }结果显示 第四个版本(线程安全版本) IT行业这么火, 涌入的人很多. 俗话说林子大了啥鸟都有. 大佬和菜鸡们两极分化的越来越严重. 为了让菜鸡们不太拖大佬的后腿, 于是大佬们针对一些经典的常见的场景, 给定了一些对应的解决方案, 这个就是 设计模式 其中单例模式就是设计模式中的一种 所谓的单例模式就是指有一个特殊类有且只有用它来创建一个对象 为什么要设计这种模式呢 拿我们线程池来举例线程池这个对象大多数时候我们并不需要创建多个假如任务很多我们只要相应调节线程池里面的线程数目即可假如创建多个线程池对象这样其实效率并不高. 单例对象的最终目的就是为了提高效率 那具体如何设计这个特殊类呢(懒汉模式) 1.构造函数私有化拷贝赋值函数删除(这样外面的用户也就不能再创建对象了) 2.类成员变量中加入类指针并用static进行修饰 3.在类内提供相应接口函数每次用户调用该接口时用类指针创建对象但是假如类指针不为空也就是已经创建了一个对象则直接返回该对象的指针不会再创建新的对象 具体改造后的代码如下 #pragma once #include iostream #include vector #include queue #include Task.hpp #include pthread.h #include Thread.hpp #include mymutex.hppconst static int N 5; //默认线程数量 template class T class ThreadPool { private:ThreadPool(int num N):_num(num){pthread_mutex_init(_mutex,nullptr);pthread_cond_init(_cond,nullptr);}ThreadPool(const ThreadPoolT tp) delete; //删除构造函数void operator(const ThreadPoolT tp) delete; //删除赋值函数public:static ThreadPoolT* GetInstance(){if(nullptr instance)//提高效率 {LockGuard lockguard(instance_lock); if(nullptr instance) //保证有且只有一个线程可以创建对象{instance new ThreadPoolT();instance-Init();instance-start();}}return instance;}~ThreadPool(){for(auto t:_threads){t.Join();}pthread_mutex_destroy(_mutex);pthread_cond_destroy(_cond);}pthread_mutex_t* Getlock(){return _mutex;}void ThreadWait(){pthread_cond_wait(_cond,_mutex); //没有任务线程自动进入等待}void ThreadWakeUp(){pthread_cond_signal(_cond); //唤醒任务队列里面的线程}//判断任务队列是否为空bool Isempty(){return _tasks.empty();}T popTask(){T t _tasks.front();_tasks.pop();return t;}void PushTask(const Tt){LockGuard lockguard(_mutex);_tasks.push(t); //任务入列ThreadWakeUp(); //唤醒线程进行工作}static void* ThreadRoutine(void* args){//将传进啦的this指针转成我们的对象这样即可访问里面的方法和成员变量ThreadPoolTask* tp static_castThreadPoolTask *(args);while (true){T t;//任务队列不为空{LockGuard lockguard(tp-Getlock());while(tp-Isempty()){tp-ThreadWait(); //假如没有任务则等待}//有任务取出对应的任务t tp-popTask();}t(); //执行任务std::cout Routine done: t.formatRes() std::endl;}}//创建对应的线程void Init(){for(int i 0;i _num;i){_threads.push_back(Thread(i,ThreadRoutine,(void*)this));} }void start(){for (auto t:_threads){ t.Run(); //调用自定义线程里面的Run函数创建相应的线程}}void Check(){for(auto t:_threads){std::cout t.name() is Running... std::endl;}} private:std::vectorThread _threads; //线程编号向量int _num; //线程数量std::queueT _tasks; //任务数量pthread_mutex_t _mutex; //锁pthread_cond_t _cond; //条件变量static ThreadPoolT* instance; //类对象指针static pthread_mutex_t instance_lock; //类对象锁 };//对对象指针进行初始化 template class T ThreadPoolT* ThreadPoolT::instance nullptr;//对类对象锁进行初始化 template class T pthread_mutex_t ThreadPoolT::instance_lock PTHREAD_MUTEX_INITIALIZER;这里有个细节需要注意 在实现GetInstance函数时我们采取双检查加锁的方式 原因在于加锁解锁必定要在临界区之前否则将毫无意义依旧会出现多个线程创建多个对象出现并发问题 但是单例只会被创建一次申请锁这个操作本身是一种消耗 因此我们在外层再套一层判断假如不为空则不会进去也就不会再因为申请锁这个操作而白白消耗 提高效率的同时还保证了线程安全
http://wiki.neutronadmin.com/news/149878/

相关文章:

  • 织梦网站怎样做百度主动推送网站建设知识文章
  • 上市公司网站建设评价佛山做外贸网站案例
  • 网站开发存在的问题备案ip 查询网站查询网站查询系统
  • 贵阳国家经济技术开发区门户网站深圳产品设计培训机构
  • 网站建设kaodezhuandroid官网入口
  • 报名网站怎么做猎聘网招聘官方网站
  • 服装工厂做网站的好处网页设计与网站建设期末考试试卷
  • 网站建设费用是多少全国企业信息查询官网系统
  • 哪个网站可以做记录视频wordpress配置qq邮箱
  • 资讯网站域名选购班级网站源码
  • 一树擎天又一个wordpress站点聊城手机网站建设价格
  • 模板网站修改教程视频学校网站建设营运预算
  • 江永网站建设网站建设及维护学习
  • 怎么做8代码网站百度高级搜索首页
  • 个人网站页脚设计wordpress媒体库显示不出来
  • 网站开发中心深圳做网站要多少钱
  • 用dw做的网站容易变形网站关键词设定
  • 郴州网站建设软件定制开发平台dw做网站有哪些用处
  • 企业网站推广推广阶段广西建设教育协会网站
  • 在哪个网站可以做试卷国外平面设计教程网站
  • 网站建设服务范围广州建立公司网站多少钱
  • 阳澄湖大闸蟹网站建设惠州网站制作专业
  • 有没有免费的企业网站建设福州网站设计哪家做的好
  • 驻马店做网站建设的公司网站代码组件
  • frontpage做网站怎么样企业型网站建设费用
  • 色块设计网站工程造价信息网官网登录
  • 怎么创建自己的网站2021年最新的网站
  • 洛阳做多屏合一网站wordpress电商平台
  • 公司建设网站费用属于什么费用东莞企业网站设计
  • 深圳网站外包公司网上商店的优势和缺陷