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

大型门户网站开发方案百度指数移动版app

大型门户网站开发方案,百度指数移动版app,武威网站制作公司服务电话,discuz可以做门户网站吗一、线程池 1、线程与进程的区别? 进程是操作系统分配资源的基本单位,线程是操作系统进行CPU调度的单位。 2、线程池的好处? 复用线程资源,减少创建和销毁线程的开销。 3、线程池是什么? 维持管理一定数量线程的…

一、线程池

1、线程与进程的区别?

进程是操作系统分配资源的基本单位,线程是操作系统进行CPU调度的单位。

2、线程池的好处?

复用线程资源,减少创建和销毁线程的开销。

3、线程池是什么?

维持管理一定数量线程的池式结构。

  • 维持:复用资源
  • 管理:线程是参与CPU调度的,如果暂时不需要线程执行,就将其进行休眠,能最大限度的使用资源。
  • 为什么是一定数量,而不是固定数量?:操作系统运行线程是通过CPU的核心去运行的,而CPU的核心数量是有限的,如果线程池中的线程数过多,超过了核心的数量,那么会带来线程切换的开销,反而降低了效率。

4、线程池解决什么问题?

  • 异步执行耗时任务,不过度占用核心线程资源(生产者线程)
    • 耗时:耗时等待(io),耗时计算。
  • 充分利用多核

5、线程池是如何解决问题的?

生产消费模型角度来看:

  • 生产者:核心线程,抛出耗时任务到队列,并唤醒一个休眠线程。
  • 消费者:线程池线程,从队列中取出任务执行;当队列为空时,线程进入休眠状态。
    在这里插入图片描述

二、具体实现

1、面向生产者线程

发布任务到线程池。

void ThreadPoll::Post(std::function<void()> task)
{m_queuePlus->Push(task);
}

2、任务队列

std::queue<std::function<void()>> m_queue;     //任务队列
//但该队列属于临界资源,不利于多线程安全,需要加互斥锁,读写锁等来保证线程安全。

使用阻塞队列,将锁封装在BlockQueue中

BlockQueue<std::function<void()>> m_queue;     //任务队列

3、维持管理一定数量线程

std::vector<std::thread> m_workthreads;     //线程集合

4、线程池线程数量的确定

  • 耗时计算任务:核心线程数 = CPU核心数,因为计算任务是CPU密集型,不会涉及到用户态和内核态的切换,全是用户态执行,所以核心线程数要和CPU的核心数一致。不过这个值是理论值,实际上,需要在该值的基础上,+1,+2,-1,-2等去测试,找到最优值。(测试单位时间内执行任务数来决定)

  • 耗时等待任务:IO密集型任务,IO在Linux下主要分为文件IO和网络IO,因为涉及到用户态和内核态的切换以及IO的等待,所以核心线程数 = 2 * CPU核心数,让一部分线程在等待IO时,能有更多的线程去执行其他任务。同理,也需要测试找到最优值。(测试单位时间内执行任务数来决定)

  • (线程等待时间 + cpu运算时间) * cpu核心线程数 / cpu运算时间 = 线程池最优核心数

5、核心线程抛出任务到队列,并唤醒一个休眠线程

void Push(const T &value) // 入队操作
{std::lock_guard<std::mutex> lock(m_mutex);m_queue.push(value);m_cond.notify_one(); // 唤醒一个等待的线程
}

6、线程池线程从队列中取出任务执行;当队列为空时,线程进入休眠状态。

void ThreadPoll::Worker()
{while (true){std::function<void()> task;if (!m_queuePlus->Pop(task))break;task();}
}bool Pop(T &value) // 出队操作,考虑正常情况与异常情况(队列为空)
{std::unique_lock<std::mutex> lock(m_mutex); // 与lock_guard相比,unique_lock可以延迟锁定,可手动调用unlock,并且同样在析构时自动释放锁。m_cond.wait(lock, [this]{ return !m_queue.empty() || m_nonblock; }); // 若队列为空,则阻塞等待,直到队列不为空或者m_nonblock为true时才继续执行。if (m_queue.empty())return false;value = m_queue.front();m_queue.pop();return true;
}

7、执行完毕,销毁线程

ThreadPoll::~ThreadPoll()
{m_queuePlus->CancelBlock();for (auto &thread : m_workthreads){if (thread.joinable())thread.join();}
}

8、结果:

在这里插入图片描述

9、优化

之前生产者和消费者共用一个队列,并且用一个互斥锁,这样会导致生产者线程和消费者线程都在等待同一个锁;线程数量少,以及任务量少时,感觉不出来,当线程数量变多,任务量多时,效率就会变得低下。

  • 优化方案:生产者对应生产者队列,消费者对应消费者队列。
//在之前阻塞队列里面封装了两个队列,一个生产者队列和一个消费者队列,两把互斥锁,一个生产者队列对应一把锁,一个消费者队列对应一把锁。
std::queue<T> prod_queue_;
std::queue<T> cons_queue_;
std::mutex prod_mutex_;
std::mutex cons_mutex_;int SwapQueue()
{std::unique_lock<std::mutex> lock(m_prod_mutex); // 与lock_guard相比,unique_lock可以延迟锁定,可手动调用unlock,并且同样在析构时自动释放锁。m_cond.wait(lock, [this]{return !m_prod_queue.empty() || m_nonblock; }); // 若队列为空,则阻塞等待,直到队列不为空或者m_nonblock为true时才继续执行。std::swap(m_prod_queue, m_cons_queue);return m_cons_queue.size();
}

在这里插入图片描述

三、总结:

  1. 进程与线程的关系

    • 进程作为操作系统资源分配的基本单位
    • 线程作为CPU调度的基本执行单元
  2. 线程池的核心优势

    • 实现线程资源的高效复用
    • 显著降低频繁创建和销毁线程的系统开销
  3. 线程池的设计原则

    • 采用池化技术管理固定数量的线程
    • 遵循"适量最优"原则,而非盲目增加线程数量
  4. 线程池的核心价值

    • 充分发挥多核CPU的计算优势
    • 实现主线程与耗时任务的异步解耦执行

四、问题:

1、为什么使用队列?

队列是一种双端口操作的数据结构。

  • 职责:生产者对应一个端口,消费者对应另一个端口。
  • 操作队列的时间复杂度为O(1),而vector为O(n),后续加锁灵活。

代码链接:
Code
0voice·Github

http://www.dtcms.com/a/516845.html

相关文章:

  • YOLOv9:重构实时目标检测的技术革命
  • 广东建设报网站深圳外贸公司排行
  • 乌克兰服装网站建设一个网站的预算
  • wordpress安装后只显示英文站北京网络安全公司排名
  • 网站开发拓扑图电话销售系统
  • 学做川菜下什么网站西部空间怎样上传网站
  • Andrej Karpathy 演讲【PyTorch at Tesla】
  • 母婴的网站建设郑州网站建设公司谷雨
  • 柳州网站建设psn118做直播教程的网站
  • 表示微调(ReFT)
  • Redis黑马 day01
  • 如何实现两台虚拟机之间的时间同步
  • 数据库接口之防止sql注入
  • Linux下搭建Activemq的Master-Slave(共享文件模式)
  • 做网站一定需要自己买主机吗wordpress 三款站群插件之比较
  • 数据结构——拓扑排序
  • 常用网站png手机商城官方网站
  • 网站开发的经验技巧网站建设实训该写哪些内容
  • 响应式网站开发 三合一建站做网站推广一般多少钱
  • P1041题解
  • 大语言模型本地部署之转录文本总结
  • 北京建设信源官方网站wordpress如何修改logo
  • 网站在那里备案做网站的属于什么行业
  • Matalb处理arxml 连线问题存储问题。
  • iOS 26 App 查看电池寿命技巧,多工具组合实践指南
  • 孝感 网站建设公众号运营总结
  • 国内高校网站建设的调查wordpress设置略缩图外链图片
  • ITSM 目前成熟度如何?为什么中小型企业总卡在半途,以及R²AIN SUITE如何让企业突围
  • 响应式购物网站设计青岛手机网站建设报价
  • AI驱动的测试:Cypress的cy.prompt功能实践