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

安徽池州做企业网站他达拉非和西地那非区别

安徽池州做企业网站,他达拉非和西地那非区别,中国住建网证书查询,福建外贸网站1.线程池原理 创建一个线程#xff0c;实现很方便。 缺点#xff1a;若并发的线程数量很多#xff0c;并且每个线程都是执行一个时间较短的任务就结束了。 由于频繁的创建线程和销毁线程需要时间#xff0c;这样的频繁创建线程会大大降低 系统的效率。 2.思考 …1.线程池原理 创建一个线程实现很方便。 缺点若并发的线程数量很多并且每个线程都是执行一个时间较短的任务就结束了。       由于频繁的创建线程和销毁线程需要时间这样的频繁创建线程会大大降低       系统的效率。 2.思考 怎么样实现线程复用让线程执行完一个任务后不被销毁还可以继续执行其他的任务 答线程池 3.思考 什么是线程池 可以点击看爱编程的大丙写的这边文章写的很好 4.线程池的组成任务队列、工作的线程、管理者线程 1任务队列 听到任务队列之后咱们在脑海里应该闪现出另外一个模型就是生产者和消费者模型。因为只要 有任务队列就离不开生产者和消费者模型。为什么要有任务队列呢就是因为他有生产者要把生 产出来的数据或者商品进行存储存储起来之后让对应的某些消费者去消费。在我们写程序的时候 就是有一些生产者线程还是负责往这个任务队列里边放任务然后有一些消费者线程负责把任务从 任务队列中取出去并且把它处理掉。在线程池里边有任务队列也就意味着这个线程池它是生产者 和消费者模型里边的一部分。哪一个部分呢这个线程池主要是负责维护一个任务队列然后再维护 若干个消费者线程。它维护的线程都是消费者线程。 那么生产者是谁呢谁使用任务队列谁就是生产者。那么这个生产者它把任务放到任务队列里边。 怎么放呢肯定是通过线程池提供的api接口把这个任务放到任务队列放进来之后这个消费 者线程通过一个循环不停地从这个任务队列里边去取任务 假设说咱们这个任务队列为空了消费者线程就需要阻塞了。可以使用条件变量把它阻塞掉就行了。 如果让消费者线程去阻塞它就放弃了CPU时间片了这个对系统的资源消耗是一点都没有的。 对于生产者来说假设这个任务队列已经满了需要阻塞生产者。当这个消费者消费了这个产品之后 任务队列就不再满了那么任务队列不再满之后咱们就让消费者把这个生产者唤醒让他们继续生 产。这个任务队列是两个角色而不是三个角色这一点要搞明白的2工作的线程 这个任务队列里边的任务都是函数地址工作的线程在处理这个任务的时候它就基于这个函数地址 对那个函数进行调用。也就说这个任务队列里边的任务都是回调函数。 什么时候去回调呢 就是当线程池里边的这个消费者线程把它取出去之后它就被调用了。如果说没有被取出来他就不 被调用了。3管理者线程 管理者线程的职责非常单一就是不停的去检测当前任务队列里边任务的个数还有当前工作的线程 的线程数然后针对于它们的数量进行一个运算。看一看现在需要添加线程还是销毁线程。干这个事 的时候可以给它设置一个频率比如说你可以让他五秒钟去做一次或者十秒钟去做一次。sleep管理 者是非常轻松的 一任务类Task的定义 #pragma once #include queue #include pthread.husing callback void (*)(void *);// 任务结构体 template typename T struct Task {TaskT(){function nullptr;arg nullptr;}TaskT(callback f, void *arg){this-arg (T *)arg;function f;}callback function;T *arg; }; 二任务队列TaskQueue的定义 template typename T class TaskQueue { public:TaskQueue();~TaskQueue();// 添加任务void addTask(TaskT task);void addTask(callback f, void *arg);// 取出一个任务TaskT takeTask();// 获取当前任务的个数inline size_t taskNumber(){return m_taskQ.size();}private:std::queueTaskT m_taskQ;pthread_mutex_t m_mutex; }; 三线程池 ThreadPool 类的声明 #pragma once #include TaskQueue.h template typename T class ThreadPool { public:// 创建线程池并初始化ThreadPool(int min, int max);// 销毁线程池~ThreadPool();// 给线程池添加任务void addTask(TaskT task);// 获取线程池中工作的线程的个数int getBusyNum();// 获取线程池中活着的线程个数int getAliveNum();private:// 工作的线程是消费者线程任务函数static void *worker(void *arg);// 管理者线程任务函数static void *manager(void *arg);// 单个线程退出void threadExit();private:// 任务队列TaskQueueT *taskQ;pthread_t managerID; // 管理者线程IDpthread_t *threadIDs; // 工作的线程IDint minNum; // 最小线程数量int maxNum; // 最大线程数量int busyNum; // 忙的线程的个数int liveNum; // 存活的线程的个数int exitNum; // 要销毁的线程个数pthread_mutex_t mutexPool; // 锁整个的线程池pthread_cond_t notEmpty; // 任务队列是不是空了bool shutdown false; // 是不是要销毁线程池static const int NUMBER 2; }; 四线程池 构造函数 template typename T ThreadPoolT::ThreadPool(int min, int max) {do{// 实例化任务队列taskQ new TaskQueueT;if (taskQ nullptr){std::cout new taskQ fail... std::endl;break;}// 根据线程的最大上限给线程数组分配内存threadIDs new pthread_t[max];if (threadIDs nullptr){std::cout new threadIDs fail... std::endl;break;}// 初始化memset(threadIDs, 0, sizeof(pthread_t) * max);minNum min;maxNum max;busyNum 0;liveNum min; // 和最小个数相等exitNum 0;// 初始化互斥锁条件变量if (pthread_mutex_init(mutexPool, NULL) ! 0 ||pthread_cond_init(notEmpty, NULL) ! 0){std::cout mutex or condition init fail...\n std::endl;break;}shutdown false;/// 创建线程 ////void *(ThreadPool::*)(void *arg) 类型的实参与 void *(*)(void *) 类型的形参不兼容// 类的静态成员或者类的外部的非类普通函数只要定义出来之后就有地址// 如果是类的成员函数并且不是静止的这个函数定义出来是没有地址的// 什么时候有地址呢我们必须要给这个类进行实例化创建类的对象这个// 函数才有地址// this指针指向当前被实例化的对象如果要是在外边new出来一个ThreadPool对象// 那么这个this指针就指向该实例化对象// 为什么要把this传给manager呢// 因为manager是一个静态方法静态方法它只能访问类里边的静态成员变量// 它不能访问类的非静态成员变量。// 因此如果我们想要访问这些非静态成员变量就必须要给这个静态方法传进去一个// 实例化对象通过传进去的这个实例化对象来访问里边的非静态成员函数和变量// 创建管理者线程,1个pthread_create(managerID, NULL, manager, this);// 根据最小线程个数创建线程for (int i 0; i min; i){pthread_create(threadIDs[i], NULL, worker, this);}return;} while (0);// 释放资源if (threadIDs)delete[] threadIDs;if (taskQ)delete taskQ; } 五工作的线程的任务函数 // 工作线程任务函数 template typename T void *ThreadPoolT::worker(void *arg) {ThreadPool *pool static_castThreadPool *(arg);// 一直不停的工作while (true){// 访问任务队列共享资源加锁pthread_mutex_lock(pool-mutexPool);// 当前任务队列是否为空如果为空工作线程阻塞while (pool-taskQ-taskNumber() 0 !pool-shutdown){//printf(thread %ld waiting...\n,pthread_self());// 阻塞工作线程pthread_cond_wait(pool-notEmpty, pool-mutexPool);// 解除阻塞之后判断是不是要销毁线程if (pool-exitNum 0){pool-exitNum--;if (pool-liveNum pool-minNum){pool-liveNum--;pthread_mutex_unlock(pool-mutexPool);pool-threadExit();}}}// 判断线程池是否被关闭了if (pool-shutdown){pthread_mutex_unlock(pool-mutexPool);pool-threadExit();}// 从任务队列中取出一个任务TaskT task pool-taskQ-takeTask();// 工作的线程1pool-busyNum;// 线程池解锁pthread_mutex_unlock(pool-mutexPool);// 执行任务printf(thread %ld start working...\n, pthread_self());// std::coutthread to_string(pthread_self()) start working...std::endl;task.function(task.arg);delete task.arg;task.arg nullptr;// 任务处理结束printf(thread %ld end working...\n, pthread_self());// std::coutthread std::string to_string(pthread_self()) end working...std::endl;pthread_mutex_lock(pool-mutexPool);pool-busyNum--;pthread_mutex_unlock(pool-mutexPool);}return nullptr; } 六线程退出函数 //线程退出 template typename T void ThreadPoolT::threadExit() {pthread_t tid pthread_self();for (int i 0; i maxNum; i){if (threadIDs[i] tid){threadIDs[i] 0;// std::coutthreadExit() called, std::string to_string(tid) exiting...std::endl;printf(threadExit() called,%ld exiting...\n, tid);break;}}pthread_exit(NULL); // 这个是标准C的函数 } 七管理者线程的任务函数 // 管理者线程任务函数 template typename T void *ThreadPoolT::manager(void *arg) {ThreadPool *pool static_castThreadPool *(arg);// 如果线程池没有关闭就一直检测while (!pool-shutdown){// 每隔3s检测一次sleep(3);// 取出线程池中任务的数量和当前线程的数量 取出工作的忙的线程的数量pthread_mutex_lock(pool-mutexPool);int queueSize pool-taskQ-taskNumber();int liveNum pool-liveNum;int busyNum pool-busyNum;pthread_mutex_unlock(pool-mutexPool);// 添加线程// 任务的个数存货的线程个数 存活的线程数 最大线程数if (queueSize liveNum liveNum pool-maxNum){pthread_mutex_lock(pool-mutexPool);int counter 0;for (int i 0; i pool-maxNum counter NUMBER pool-liveNum pool-maxNum; i){if (pool-threadIDs[i] 0){pthread_create(pool-threadIDs[i], NULL, worker, pool);counter;pool-liveNum;}}pthread_mutex_unlock(pool-mutexPool);}// 销毁多余的线程// 忙的线程 * 2 存活的线程数 存活的线程 最小线程数if (busyNum * 2 liveNum liveNum pool-minNum){pthread_mutex_lock(pool-mutexPool);pool-exitNum NUMBER;pthread_mutex_unlock(pool-mutexPool);// 让工作的线程自杀for (int i 0; i NUMBER; i){pthread_cond_signal(pool-notEmpty);}}}return nullptr; } 八给线程池添加任务 // 给线程池添加任务 template typename T void ThreadPoolT::addTask(TaskT task) {if (shutdown){return;}// 添加任务不需要加锁任务队列中有锁taskQ-addTask(task);// 唤醒工作的线程pthread_cond_signal(notEmpty); // 通知消费者消费 } 九获取线程池忙的线程个数和活着的线程个数 template typename T int ThreadPoolT::getBusyNum() {pthread_mutex_lock(mutexPool);int busyNum this-busyNum;pthread_mutex_unlock(mutexPool);return busyNum; }template typename T int ThreadPoolT::getAliveNum() {pthread_mutex_lock(mutexPool);int aliveNum this-liveNum;pthread_mutex_unlock(mutexPool);return aliveNum; }十线程池析构 template typename T ThreadPoolT::~ThreadPool() {// 关闭线程池shutdown true;// 阻塞回收管理者线程pthread_join(managerID, NULL);// 唤醒阻塞的消费者线程for (int i 0; i liveNum; i){pthread_cond_signal(notEmpty);}// 释放堆内存if (taskQ) delete taskQ;if (threadIDs) delete[] threadIDs;pthread_mutex_destroy(mutexPool);pthread_cond_destroy(notEmpty); } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 完整代码 TaskQueue.h #pragma once #include queue #include pthread.husing callback void (*)(void *);// 任务结构体 template typename T struct Task {TaskT(){function nullptr;arg nullptr;}TaskT(callback f, void *arg){this-arg (T *)arg;function f;}callback function;T *arg; };template typename T class TaskQueue { public:TaskQueue();~TaskQueue();// 添加任务void addTask(TaskT task);void addTask(callback f, void *arg);// 取出一个任务TaskT takeTask();// 获取当前任务的个数inline size_t taskNumber(){return m_taskQ.size();}private:std::queueTaskT m_taskQ;pthread_mutex_t m_mutex; }; TaskQueue.cpp #include TaskQueue.h #include pthread.htemplate typename T TaskQueueT::TaskQueue() {// 初始化互斥锁pthread_mutex_init(m_mutex, NULL); }template typename T TaskQueueT::~TaskQueue() {// 销毁互斥锁pthread_mutex_destroy(m_mutex); }template typename T void TaskQueueT::addTask(TaskT task) {pthread_mutex_lock(m_mutex);m_taskQ.push(task);pthread_mutex_unlock(m_mutex); }template typename T TaskT TaskQueueT::takeTask() {TaskT t;pthread_mutex_lock(m_mutex);if (!m_taskQ.empty()){t m_taskQ.front();m_taskQ.pop();}pthread_mutex_unlock(m_mutex);return t; }template typename T void TaskQueueT::addTask(callback f, void *arg) {pthread_mutex_lock(m_mutex);m_taskQ.push(TaskT(f, arg));pthread_mutex_unlock(m_mutex); } ThreadPool.h #pragma once #include TaskQueue.h template typename T class ThreadPool { public:// 创建线程池并初始化ThreadPool(int min, int max);// 销毁线程池~ThreadPool();// 给线程池添加任务void addTask(TaskT task);// 获取线程池中工作的线程的个数int getBusyNum();// 获取线程池中活着的线程个数int getAliveNum();private:// 工作的线程是消费者线程任务函数static void *worker(void *arg);// 管理者线程任务函数static void *manager(void *arg);// 单个线程退出void threadExit();private:// 任务队列TaskQueueT *taskQ;pthread_t managerID; // 管理者线程IDpthread_t *threadIDs; // 工作的线程IDint minNum; // 最小线程数量int maxNum; // 最大线程数量int busyNum; // 忙的线程的个数int liveNum; // 存活的线程的个数int exitNum; // 要销毁的线程个数pthread_mutex_t mutexPool; // 锁整个的线程池pthread_cond_t notEmpty; // 任务队列是不是空了bool shutdown false; // 是不是要销毁线程池static const int NUMBER 2; }; ThreadPool.cpp #include ThreadPool.h #include iostream #include string.h #include stdlib.h#include unistd.htemplate typename T ThreadPoolT::ThreadPool(int min, int max) {do{// 实例化任务队列taskQ new TaskQueueT;if (taskQ nullptr){std::cout new taskQ fail... std::endl;break;}// 根据线程的最大上限给线程数组分配内存threadIDs new pthread_t[max];if (threadIDs nullptr){std::cout new threadIDs fail... std::endl;break;}// 初始化memset(threadIDs, 0, sizeof(pthread_t) * max);minNum min;maxNum max;busyNum 0;liveNum min; // 和最小个数相等exitNum 0;// 初始化互斥锁条件变量if (pthread_mutex_init(mutexPool, NULL) ! 0 ||pthread_cond_init(notEmpty, NULL) ! 0){std::cout mutex or condition init fail...\n std::endl;break;}shutdown false;/// 创建线程 ////void *(ThreadPool::*)(void *arg) 类型的实参与 void *(*)(void *) 类型的形参不兼容// 类的静态成员或者类的外部的非类普通函数只要定义出来之后就有地址// 如果是类的成员函数并且不是静止的这个函数定义出来是没有地址的// 什么时候有地址呢我们必须要给这个类进行实例化创建类的对象这个// 函数才有地址// this指针指向当前被实例化的对象如果要是在外边new出来一个ThreadPool对象// 那么这个this指针就指向该实例化对象// 为什么要把this传给manager呢// 因为manager是一个静态方法静态方法它只能访问类里边的静态成员变量// 它不能访问类的非静态成员变量。// 因此如果我们想要访问这些非静态成员变量就必须要给这个静态方法传进去一个// 实例化对象通过传进去的这个实例化对象来访问里边的非静态成员函数和变量// 创建管理者线程,1个pthread_create(managerID, NULL, manager, this);// 根据最小线程个数创建线程for (int i 0; i min; i){pthread_create(threadIDs[i], NULL, worker, this);}return;} while (0);// 释放资源if (threadIDs)delete[] threadIDs;if (taskQ)delete taskQ; }// 工作线程任务函数 template typename T void *ThreadPoolT::worker(void *arg) {ThreadPool *pool static_castThreadPool *(arg);// 一直不停的工作while (true){// 访问任务队列共享资源加锁pthread_mutex_lock(pool-mutexPool);// 当前任务队列是否为空如果为空工作线程阻塞while (pool-taskQ-taskNumber() 0 !pool-shutdown){//printf(thread %ld waiting...\n,pthread_self());// 阻塞工作线程pthread_cond_wait(pool-notEmpty, pool-mutexPool);// 解除阻塞之后判断是不是要销毁线程if (pool-exitNum 0){pool-exitNum--;if (pool-liveNum pool-minNum){pool-liveNum--;pthread_mutex_unlock(pool-mutexPool);pool-threadExit();}}}// 判断线程池是否被关闭了if (pool-shutdown){pthread_mutex_unlock(pool-mutexPool);pool-threadExit();}// 从任务队列中取出一个任务TaskT task pool-taskQ-takeTask();// 工作的线程1pool-busyNum;// 线程池解锁pthread_mutex_unlock(pool-mutexPool);// 执行任务printf(thread %ld start working...\n, pthread_self());// std::coutthread to_string(pthread_self()) start working...std::endl;task.function(task.arg);delete task.arg;task.arg nullptr;// 任务处理结束printf(thread %ld end working...\n, pthread_self());// std::coutthread std::string to_string(pthread_self()) end working...std::endl;pthread_mutex_lock(pool-mutexPool);pool-busyNum--;pthread_mutex_unlock(pool-mutexPool);}return nullptr; }//线程退出 template typename T void ThreadPoolT::threadExit() {pthread_t tid pthread_self();for (int i 0; i maxNum; i){if (threadIDs[i] tid){threadIDs[i] 0;// std::coutthreadExit() called, std::string to_string(tid) exiting...std::endl;printf(threadExit() called,%ld exiting...\n, tid);break;}}pthread_exit(NULL); // 这个是标准C的函数 }// 管理者线程任务函数 template typename T void *ThreadPoolT::manager(void *arg) {ThreadPool *pool static_castThreadPool *(arg);// 如果线程池没有关闭就一直检测while (!pool-shutdown){// 每隔3s检测一次sleep(3);// 取出线程池中任务的数量和当前线程的数量 取出工作的忙的线程的数量pthread_mutex_lock(pool-mutexPool);int queueSize pool-taskQ-taskNumber();int liveNum pool-liveNum;int busyNum pool-busyNum;pthread_mutex_unlock(pool-mutexPool);// 添加线程// 任务的个数存货的线程个数 存活的线程数 最大线程数if (queueSize liveNum liveNum pool-maxNum){pthread_mutex_lock(pool-mutexPool);int counter 0;for (int i 0; i pool-maxNum counter NUMBER pool-liveNum pool-maxNum; i){if (pool-threadIDs[i] 0){pthread_create(pool-threadIDs[i], NULL, worker, pool);counter;pool-liveNum;}}pthread_mutex_unlock(pool-mutexPool);}// 销毁多余的线程// 忙的线程 * 2 存活的线程数 存活的线程 最小线程数if (busyNum * 2 liveNum liveNum pool-minNum){pthread_mutex_lock(pool-mutexPool);pool-exitNum NUMBER;pthread_mutex_unlock(pool-mutexPool);// 让工作的线程自杀for (int i 0; i NUMBER; i){pthread_cond_signal(pool-notEmpty);}}}return nullptr; }// 给线程池添加任务 template typename T void ThreadPoolT::addTask(TaskT task) {if (shutdown){return;}// 添加任务不需要加锁任务队列中有锁taskQ-addTask(task);// 唤醒工作的线程pthread_cond_signal(notEmpty); // 通知消费者消费 }template typename T int ThreadPoolT::getBusyNum() {pthread_mutex_lock(mutexPool);int busyNum this-busyNum;pthread_mutex_unlock(mutexPool);return busyNum; }template typename T int ThreadPoolT::getAliveNum() {pthread_mutex_lock(mutexPool);int aliveNum this-liveNum;pthread_mutex_unlock(mutexPool);return aliveNum; }template typename T ThreadPoolT::~ThreadPool() {// 关闭线程池shutdown true;// 阻塞回收管理者线程pthread_join(managerID, NULL);// 唤醒阻塞的消费者线程for (int i 0; i liveNum; i){pthread_cond_signal(notEmpty);}// 释放堆内存if (taskQ) delete taskQ;if (threadIDs) delete[] threadIDs;pthread_mutex_destroy(mutexPool);pthread_cond_destroy(notEmpty); } main.cpp #include iostream #include pthread.h #include ThreadPool.h #include ThreadPool.cpp #include TaskQueue.cpp #include unistd.h #include stdlib.h #include stdio.hvoid taskFunc(void *arg) {int num *(int *)arg;printf(thread %ld is working, number %d \n, pthread_self(), num);sleep(1); }int main() {// 创建线程池ThreadPoolint pool(3, 10);for (int i 0; i 100; i){int *num new int(i 100);*num i 100;pool.addTask(Taskint(taskFunc, num));}sleep(20);return 0; } 跟着这个老师的教程学习的总结的笔记  手写线程池 - C改C版 | 爱编程的大丙 (subingwen.cn)https://subingwen.cn/linux/threadpool-cpp/
http://www.hkea.cn/news/14518884/

相关文章:

  • 营销网站 需求说明柳江区城乡住房建设局网站
  • 荆门公司做网站深圳小程序开发费用
  • 金属建材企业网站建设方案网页制作平台
  • 国家重大建设项目库网站群晖 wordpress 域名
  • 重庆网站排名推广上海手机网站建设电话
  • 哈尔滨速成网站建设区域代理加盟项目
  • 湘潭建设网站公司展览展示设计必看网站
  • 27WordPress主题seo策略分析
  • 在线制作图片代码谷歌seo优化怎么做
  • 网站开发所需要注意的问题小程序价格表一览表
  • 沈阳百度首页优化网站seo怎么填写
  • 信息发布型网站是企业网站的什么asp.net 网站管理工具
  • 一个网站做多少页面数量合适怎么模仿一个网站
  • 龙岩网站建设极速建站89点班组建设网站
  • 临沂阿里巴巴网站建设湖南网站建设公司排名
  • 济南网站建设飞鸟广州怎么建设一个网站
  • 国外网站会让国内人做吗公司注册地址备案流程
  • 湖南长沙网站建设公司电话那个网站做搬家推广比较好
  • 哪里有做网站系统房地产网站互动设计公司
  • 自学考试网站建设与管理事业单位微信公众号怎么创建
  • 做网站公司 郑州泰安专业的网站建设
  • 想要网站推广页面专业网站建设网站推广
  • 戴尔网站建设的目的商丘在线商城
  • 便宜的网站建设广州建设银行招聘网站
  • 手机版网站如何做wordpress 3.6
  • 酒泉网站建设服务dw设计网页步骤
  • 做网站代理怎么赚钱做外贸网站应该关注哪些地方
  • 郑州免费网站建设有彩虹代刷源码怎么做网站
  • 企业招聘网站哪个最好竞价推广代运营
  • 东莞做网站哪个公司最好在手机上怎么做微电影网站吗