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

沈阳高端网站建设中国第三波疫情将在9月份

沈阳高端网站建设,中国第三波疫情将在9月份,网站开发团队成员,wordpress多站显示不正常目录 1.认识线程池 什么是线程池 线程池的优点 线程池的使用场景 2.线程池的实现 线程池的组成 线程池之间的关系 线程池的实现代码 任务类型 线程池类型 主程序 1.认识线程池 什么是线程池 线程池(Thread Pool)是线程的一种使用方式。它通…

目录

1.认识线程池

什么是线程池

线程池的优点

线程池的使用场景

2.线程池的实现

线程池的组成

线程池之间的关系 

线程池的实现代码

任务类型

线程池类型

主程序


1.认识线程池

什么是线程池

线程池(Thread Pool)是线程的一种使用方式。它通过预先创建一组线程并管理它们的生命周期,来提高多线程应用程序的性能和资源利用率。线程池的核心思想是减少在创建和销毁线程时所产生的开销

线程池的优点

  • 减少开销:线程的创建和销毁是有开销的,线程池通过复用线程减少了这种开销。

  • 提高响应速度:当任务到达时,线程池中已经有现成的线程可以立即执行任务,而不需要等待线程创建。

  • 提高线程的可控性:线程池可以统一管理线程的生命周期、数量和优先级,使得多线程编程更加可控。

  • 防止资源耗尽:通过限制线程的数量,线程池可以防止系统因创建过多线程而耗尽资源。

线程池的使用场景

1. Web 服务器处理请求:Web 服务器需要同时处理大量客户端请求,每个请求通常是一个短期任务(如 HTTP 请求)。使用线程池可以避免为每个请求创建和销毁线程的开销,提高服务器的响应速度和资源利用率。

2. 数据库连接池:数据库操作通常是 I/O 密集型任务,频繁创建和销毁数据库连接会消耗大量资源。通过线程池管理数据库连接,可以复用连接,减少创建和销毁连接的开销。

3. 异步任务处理:某些任务不需要立即执行,可以异步处理(如日志记录、邮件发送、消息推送等)。将任务提交到线程池中异步执行,避免阻塞主线程。

4. 批量数据处理:需要对大量数据进行处理(如文件解析、数据清洗、批量计算等),这些任务可以并行执行。将数据分片后提交到线程池中并行处理,提高处理效率。

关于线程池的应用还有很多,笔者就不一 一赘述了。

2.线程池的实现

线程池的组成

线程池内部主要有一个任务队列用于存储任务,还有一批线程从任务队列中获取任务并执行。任务队列中的任务通过一个控制线程传递进来,并且控制线程还要管理好线程池的生命周期,但是控制线程并不属于线程池

线程池之间的关系 

线程池代码中的角色有主线程和线程池中的从线程,主线程只有一个,从线程有多个,主线程往任务队列中放数据,从线程从任务队列中获取数据;此时的任务队列就是主线程和从线程之间的共享资源(也是临界资源)。因此,我们要讨论线程池中各角色之间的关系,只有讨论清楚关系了才能写出正确的并且健壮的代码。

  • 主线程和主线程之间 —— 主线程只有一个,不讨论。
  • 主线程和从线程之间 —— 互斥和同步:主线程在放数据的时候,从线程不能来获取数据,否则获取到的数据可能不完整,他们之间需要互斥的访问临界资源。而主线程生产数据之后,需要通知从线程来拿,任务队列中没有数据的时候,从线程需要进行排队等待,因此,他们之间具有同步关系。
  • 从线程和从线程之间 —— 互斥和同步:一个线程在拿数据,另一个线程就不能拿,否则可能拿到一样的数据,因此,他们之间需要互斥。为了避免某些进程竞争锁的能力太强导致的线程饥饿问题,当任务队列为空的时候,多个线程需要在条件变量下排队等待,因此,他们之间需要保持同步。

线程池的实现代码

我们设计的代码需要一个任务类型、一个线程池类型、一个主程序即可

任务类型

我们的任务类型只是简单的做一下加法即可,有想法的读者可以设计自己的任务类型。

#include <iostream>
#include <string>class Task
{
public:Task() {}Task(int num1, int num2) : _num1(num1), _num2(num2), _result(0){}void Excute(){_result = _num1 + _num2;}void ResultToString() // 打印计算结果{std::cout << "Excute Task: " << std::to_string(_num1) + "+" + std::to_string(_num2) + "=" + std::to_string(_result) << std::endl;}std::string DebugToString()  // 打印生产的任务{return std::to_string(_num1) + "+" + std::to_string(_num2) + "=?";}~Task(){}
private:int _num1;int _num2;int _result;
};

线程池类型

#include <iostream>
#include <queue>
#include <pthread.h>
#include <unistd.h>
#include "task.hpp"#define THREAD_NUM 5template<class T>
class ThreadPool
{
private:int _thread_num;             // 线程个数std::queue<T*> _task_queue;  // 任务队列pthread_mutex_t _lock;       // 互斥量,用于保护临界资源 —— 任务队列pthread_cond_t _cond;        // 条件变量,维护线程池中的线程按照
private:void LockQueue() {pthread_mutex_lock(&_lock);}void UnLockQueue() {pthread_mutex_unlock(&_lock);}void WakeUpOne() {pthread_cond_signal(&_cond);}void ThreadWait(){pthread_cond_wait(&_cond, &_lock);}bool IsEmptyQueue() {return _task_queue.empty();}static void *handler(void *arg) {ThreadPool* tp_ptr = (ThreadPool*)arg;while(true) {// 申请锁tp_ptr->LockQueue();// 判断任务队列是否为空  如果为空就让线程去等待while(tp_ptr->IsEmptyQueue()){tp_ptr->ThreadWait();}// 代码走到这里说明任务队列不为空Task *task;             // 输出型参数,用于获取任务 tp_ptr->GetTask(&task); // 获取任务tp_ptr->UnLockQueue();  // 释放锁task->Excute();         // 执行任务task->ResultToString(); // 打印执行结果delete task;            // 任务是malloc的,使用完需要delete}return NULL;}public:ThreadPool(int num = THREAD_NUM):_thread_num(num){// 构造时初始化互斥量和条件变量pthread_mutex_init(&_lock, NULL);pthread_cond_init(&_cond, NULL);}~ThreadPool() {// 析构时销毁互斥量和条件变量pthread_mutex_destroy(&_lock);pthread_cond_destroy(&_cond);}bool InitThreadPool() {pthread_t tid;// 创建一批线程for (int i = 0; i < _thread_num; i++) {int ret = pthread_create(&tid, NULL, handler, this);if (ret != 0) {std::cout<<"create pool thread error\n";return false;}}return true;}void PushTask(Task *task) {// 加锁LockQueue();// 向任务队列中放数据_task_queue.push(task);// 通知线程池中正在等待的线程来获取任务WakeUpOne();// 解锁UnLockQueue();}void GetTask(Task **task) {*task = _task_queue.front();_task_queue.pop();}
};

主程序

#include "ThreadPool.hpp"int main()
{// 定义线程池ThreadPool<Task> thread_pool;// 初始化线程池if( thread_pool.InitThreadPool()){std::cout << "Create threadpool success" << std::endl; }srand(time(NULL));while(true) {// 主线程创建任务int num1 = rand()%1000;int num2 = rand()%1000;Task* task = new Task(num1, num2);// 打印创建的任务std::cout << "Create Task: " << task->DebugToString() << std::endl;// 向任务队列中放入任务thread_pool.PushTask(task);// 每个1秒创建一个线程sleep(1);}return 0;
}

运行结果:

  • 可以看到主线程创建的任务被线程池中的线程获取并执行了。
http://www.dtcms.com/wzjs/429837.html

相关文章:

  • 国外美容院网站北京网站
  • 天津网站建设公司宁波seo关键词排名
  • 优质网站建设服务厦门百度广告开户
  • 阿里云做网站教程怎么做电商新手入门
  • ssh实训做网站代码下载西安网站seo公司
  • 大业推广网站怎么接广告赚钱
  • b站推广网站2024不用下载百度快照怎么用
  • 信云科技的vps怎么做网站企业seo排名优化
  • 实木餐桌椅网站建设公司网站推广哪家好
  • 网站建设 开发的团队需要几个人大庆黄页查询电话
  • 沧州做网站的公司排名推广公众号的9种方法
  • 做学校网站素材图片大全电子网址怎么创建
  • 做网站每个月可以赚多少宣传方式
  • 上海市人民政府郑州网站seo服务
  • 建网站要多少钱呢帮平台做推广怎么赚钱
  • 一个企业网站如何能放到互联网上 vps排名优化网站seo排名
  • 摄影网站的需求分析最近一周的国内新闻
  • 汕头今日疫情最新情况广州:推动优化防控措施落
  • 网站提交至google郑州学校网站建设
  • 齐河网站建设关键词推广
  • 做网站有视频教吗成都网站seo厂家
  • php网页设计完整代码南京seo按天计费
  • 东莞 网站建设 保健品b2b网站平台有哪些
  • 哈尔滨建设发展集团有限责任公司网站打开速度优化
  • 做年会的网站青岛seo精灵
  • 西安微信商城网站设计外贸平台排行榜前十名
  • 网站制作教程ppt东莞产品网络推广
  • 网站建设 分析深圳网站制作哪家好
  • 游戏类网站欣赏深圳防疫措施优化
  • 免费网站空间怎么搜索推广代运营