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

网站开源系统注册域名在哪里注册

网站开源系统,注册域名在哪里注册,着力加强网站内容建设,比较好的企业网站[Linux]线程池 文章目录 [Linux]线程池线程池的概念线程池的优点线程池的应用场景线程池的实现 线程池的概念 线程池是一种线程使用模式。线程池是一种特殊的生产消费模型,用户作为生产者,线程池作为消费者和缓冲区。 线程过多会带来调度开销&#xff0c…

[Linux]线程池

文章目录

  • [Linux]线程池
    • 线程池的概念
    • 线程池的优点
    • 线程池的应用场景
    • 线程池的实现

线程池的概念

线程池是一种线程使用模式。线程池是一种特殊的生产消费模型,用户作为生产者,线程池作为消费者和缓冲区。

线程过多会带来调度开销,进而影响缓存局部和整体性能,而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。

线程池的优点

  • 线程池避免了在处理短时间任务时创建与销毁线程的代价。
  • 线程池不仅能够保证内核充分利用,还能防止过分调度。

注意: 线程池中可用线程的数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。

线程池的应用场景

  1. 需要大量的线程来完成任务,且完成任务的时间比较短。
  2. 对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
  3. 接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。

线程池的实现

下面我们实现一个简单的线程池,线程池中提供了一个任务队列,以及若干个线程(多线程)。

image-20231029145843142

  • 线程池中的多个线程负责从任务队列当中拿任务,并将拿到的任务进行处理。
  • 线程池对外提供一个Push接口,用于让外部线程能够将任务Push到任务队列当中。

线程池的代码如下:

#pragma once#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <vector>
#include <queue>const 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);}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);}T getTask(){T t = _tasks.front();_tasks.pop();return t;}bool isEmpty(){return _tasks.empty();}static void *threadRoutine(void *args){pthread_detach(pthread_self());ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);while (true){tp->LockQueue();while (tp->isEmpty()){tp->threadWait();}T t = tp->getTask();tp->UnLockQueue();t.Run();//任务处理}}void Start(){pthread_t tid;for (int i = 0; i < _num; i++){pthread_create(&tid, nullptr, threadRoutine, this);}}void PushTask(T &task) // 添加任务{LockQueue();_tasks.push(task);threadWakeUP();UnLockQueue();}~ThreadPool(){pthread_mutex_destroy(&_mutex);pthread_cond_destroy(&_cond);}private:int _num;                        // 线程数std::queue<T> _tasks;            // 任务队列pthread_mutex_t _mutex; // 保证互斥访问任务队列这一共享资源pthread_cond_t _cond;   // 根据任务队列中的任务数量控制线程的等待和运行
};

为什么线程池中需要有互斥锁和条件变量?

互斥锁: 任务队列是一个共享资源,外部线程可以调用添加任务的接口访问任务队列,线程池内部的线程可以直接访问任务队列处理任务,可能会造成任务队列的并发访问问题,因此需要利用互斥锁保护任务队列中的数据。

条件变量: 线程池当中的线程要从任务队列里拿任务,前提条件是任务队列中必须要有任务,因此线程池当中的线程在拿任务之前,需要先判断任务队列当中是否有任务,若此时任务队列为空,那么该线程应该进行等待,直到任务队列中有任务时再将其唤醒,因此我们需要引入条件变量。

当外部线程向任务队列中Push一个任务后,此时可能有线程正处于等待状态,因此在新增任务后需要唤醒在条件变量下等待的线程。

为什么线程池中的线程执行例程需要设置为静态方法?

使用pthread_create函数创建线程时,需要为创建的线程传入一个执行方法threadRoutine,该执行方法只有一个参数类型为void的参数,以及返回类型为void的返回值。

如果threadRoutine作为类的成员函数,该函数的第一个参数是隐藏的this指针,无法通过编译。而静态成员函数属于类,而不属于某个对象,也就是说静态成员函数是没有隐藏的this指针的,因此我们需要将threadRoutine设置为静态方法,此时threadRoutine函数才真正只有一个参数类型为void的参数。

但是在静态成员函数内部无法调用非静态成员函数,而我们需要在threadRoutine函数当中调用该类的某些非静态成员函数。因此我们需要在创建线程时,向threadRoutine函数传入的当前对象的this指针,此时我们就能够通过该this指针在threadRoutine函数内部调用非静态成员函数了。

任务类型的设计

由于线程池编写的是模板化的,因此任务类型可以是任意的,但是由于处理任务的逻辑是通过调用任务的Run函数,因此任务类中必须实现Run函数才能使用该线程池。

例如,实现一个计算任务类如下:

#include <cstdlib>
#include <iostream>class Task
{
public:Task(int x, int y, char op) : _x(x), _y(y), _op(op), _result(0), _exitcode(0){}void Run()//对传入数据进行操作{switch (_op){case '+':_result = _x + _y;break;case '-':_result = _x - _y;break;case '*':_result = _x * _y;break;case '/':if (_y == 0) _exitcode = -1;else_result = _x / _y;break;case '%':if (_y == 0) _exitcode = -2;else_result = _x % _y;break;default:break;}std::string result = std::to_string(_x) + _op +  std::to_string(_y) + "=" + std::to_string(_result) + "(exicode:" + std::to_string(_exitcode);std::cout << result << std::endl;}private:int _x;//左操作数int _y;//右操作数char _op;//操作符int _result;//算数结果int _exitcode;//退出码
};

线程池内的线程在从任务队列拿出任务进行处理的过程,并不需要关心这些任务的类型和来源,只需要拿到任务后执行对应的Run方法即可。

主线程实现

主线程只需要不断向任务队列当中Push任务就行了,此后线程池当中的线程会从任务队列当中获取到这些任务并进行处理。

#include "ThreadPoolv1.hpp"
#include "Task.hpp"
#include <memory>
#include <ctime>using namespace std;int main()
{std::unique_ptr<ThreadPool<Task>> tp(new ThreadPool<Task>());tp->Start();time(nullptr);const char* ops = "+-*/%";while(true){int x, y;x = rand() % 50;y = rand() % 50;char op = ops[rand()%5];Task t(x, y, op);tp->PushTask(t);sleep(1);}return 0;
}

运行代码后会产生六个线程,其中一个是主线程,另外五个是线程池内处理任务的线程:

image-20231029152724549

http://www.ds6.com.cn/news/15531.html

相关文章:

  • 网页设计制作网站开发建设新手建站基础入门到精通视频教程最新域名查询ip
  • 营销网站开发系统壹起航网络推广的目标
  • 手机wap网站制作需要多少钱深圳新闻今日最新
  • 深圳做网站排名公司哪家好你就知道
  • 自助网站建设哪家效益快广告营销顾问
  • wordpress站点前台请求数过多seo自动工具
  • 香港wordpress不限域名石狮seo
  • 网站建设计划百度里面的站长工具怎么取消
  • 运城做网站西安网站推广排名
  • wordpress w3 total cache 编码错误立即优化在哪里
  • 网站怎么添加模块重庆seo网站建设
  • 网站设计评价by网站域名
  • 唐山高端网站建设泰安网站推广优化
  • 阳泉住房与城乡建设厅网站搜索引擎排名营销
  • 公司建设网站的请示百度最怕哪个部门去投诉
  • 可以做ppt的网站有哪些深圳seo云哥
  • 增城网站建设怎么选择长沙百度推广优化排名
  • 哈尔滨网站建设工作今天的新闻 最新消息摘抄
  • 做艺术教育类网站如何申请百度刷排名seo
  • 沈阳市城乡建设网站自己建网站
  • dw怎么做网站轮播图深圳推广公司有哪些
  • 做网站怎么导入源码宁波seo关键词培训
  • wordpress 关键词优化廊坊关键词优化平台
  • 用php做的企业网站作业最新国内新闻事件今天
  • 做公司网站费用免费网站模板库
  • 网站怎么做网上报名今日国际新闻头条15条简短
  • 龙华做网站多少钱网络营销推广服务商
  • 网站开发属于哪个部门淘宝直通车
  • 怎么做切片网站百度手机助手下载苹果版
  • 设计师网站十大网站排名周口seo公司