提高网站的访问速度/信阳seo
文章目录
- 线程池
- 线程池原理
- 代码示例
- 单例模式
- 饿汉模式
- 懒汉模式
- 饿汉懒汉对比
- 其他的锁
线程池
线程池原理
线程池是一种线程使用模式。在多线程应用中,若每有一个任务,线程就去调度相应的函数去创建,当任务过多时,每次都去调度且每次用完销毁,影响效率,加重CPU的负载;
而线程池是提前创建好的一批线程(不固定长度),没任务时就挂起等待,有任务分配时就被唤醒,等待分配任务,但也要具体分场景,例如任务时间短,且任务量大的时候
线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量
应用场景:
-
需要大量的线程来完成任务,且完成任务的时间比较短。 WEB服务器完成网页请求这样的任务,使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大,你可以想象一个热门网站的点击次数。
但对于长时间的任务,比如一个Telnet连接请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大多了
-
对性能要求苛刻的应用,比如要求服务器迅速响应客户请求
-
接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用
突发性大量客户请求,在没 有线程池情况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程 可能使内存到达极限,出现错误
代码示例
- 创建一个任务队列和线程池
- 外部向任务队列Push任务,任务队列唤醒线程池,并Pop给线程池,线程池分配出线程去执行任务
/*****************************************任务队列*************************************************/
#pragma once
#include <string>
#include <queue>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <ctime>
#include <cstdlib>
#include "Task.hpp"namespace dd
{const int Num = 5;template <class T>class ThreadPool{
public:ThreadPool(int num = Num) : _num(num){pthread_mutex_init(&_mtx, nullptr);pthread_cond_init(&_cond, nullptr);}~ThreadPool() {pthread_mutex_destroy(&_mtx);pthread_cond_destroy(&_cond);}//加锁void Lock(){pthread_mutex_lock(&_mtx);}//解锁void Unlock(){pthread_mutex_unlock(&_mtx);}//判断空bool isEmpty(){return _task_queue.empty();}//唤醒条件变量的等待队列void WakeUp(){pthread_cond_signal(&_cond);} //条件变量,挂起等待void wait(){pthread_cond_wait(&_cond,&_mtx);}//创建线程池void InitThreadPool(){pthread_t tid;for (int i = 0; i < num_; ++i){pthread_create(&tid, nullptr, Rountine, (void*)this);}}// 在类内要让线程执行类内成员函数是不可行的// 普通成员函数中,参数默认一个this指针// 需要调用静态方法static void* Rountine(void* args){//static函数不能访问类内成员和函数,所以让外面实例化的对象,调用Init通过this传进来ThreadPool<T>* tp = (ThreadPool<T>*)args;pthread_detach(pthread_self());while (true){// 从任务队列中拿任务 为了能拿任务队列里的东西,需要传递this指针tp->Lock();while (tp->isEmpty()) {tp->wait();}//拿任务T t;tp->Poptask(&t);tp->Unlock();//拿完任务,任务就属于调用Pop的那个线程了,不是临界资源了//执行任务,执行任务时就不用占着锁了t.Run();}} //放任务,放任务时访问的是临界资源:任务队列,所以要上锁void Pushtask(const T& in){Lock();task_queue_.push(in);Unlock();WakeUp();}//拿任务,拿任务时的上下文是有锁的,所以不需要在这里上锁void Poptask(T* out){*out = task_queue_.front();task_queue_.pop();} private:int _num;// 线程池中的线程数量std::queue<T> _task_queue;pthread_mutex_t _mtx;pthread_cond_t _cond;};
}/**********************************************************************************************/
#pragma once
#include <iostream>
#include <pthread.h>
namespace dd
{class Task
{
public:Task(){}Task(int x,int y,char op):_x(x),_y(y),_op(op){}int Run(){int ret = 0;switch(_op){case '+':ret = _x + _y;break;case '-':ret = _x - _y;break;case '*':ret = _x * _y;break;case '/':ret = _x / _y;break;case '%':ret = _x % _y;break;default:break;}//std::cout << _x << _op << _y << " = " << ret << std::endl;std::cout << pthread_self() << ": " << _x << _op << _y << " = " << ret << std::endl;}
private:int _x;int _y;char _op;};}/**********************************************************************************************/
#include "thread_pool.hpp"
#include "Task.hpp"
using namespace dd;
int main()
{ThreadPool<Task>* tp = new ThreadPool<Task>();//创建线程tp->InitThreadPool();srand((unsigned int)time(nullptr));while (true){// 主线程push任务 真实情况中 任务一般是从网络来的Task t(rand() % 20 + 1, rand() % 10 + 1, "+-*/%"[rand() % 5]);tp->pushtask(t);// sleep(1);}return 0;
}
单例模式
单例模式是指在整个系统生命周期内,保证在内存中,一个类只会创建且仅创建一次对象的设计模式,确保该类的唯一性
可以节省内存,节约资源,对于一般频繁创建和销毁对象的可以使用单例模式
可以避免对资源的多重占用
例如在很多服务器开发场景中, 经常需要让服务器加载很多的数据 (上百G) 到内存中. 此时往往要用一个单例的类来管理这些数据;也就是这么大的数据在内存只需要有一份,避免数据冗余(例如动态库)
单例类的特点
- 构造函数和析构函数为私有类型,目的是禁止外部构造和析构
- 拷贝构造函数和赋值构造函数是私有类型,目的是禁止外部拷贝和赋值,确保实例的唯一性
- 类中的成员变量是静态的,静态的无论实例化多少对象,都只有(公用)一个静态成员变量
- 类中要有一个获取实例的静态方法,可以全局访问
单例模式可以分为两种模式:饿汉模式、懒汉模式
饿汉模式
注意几点细节:
-
需要将构造函数,拷贝构造函数,赋值运行符重载函数屏蔽,防止在外部实例化对象
-
在类中创建一个静态类对象,该静态类对象,会在程序运行时创建,需要在类外初始化
-
类中写一个接口(静态),返回静态类对象的地址。因为无法调用拷贝构造,不能直接返回类对象
template <typename T>
class Singleton
{static T data;//static Singleton<T> dataSingelTon() = delete;SingelTon(const SingelTon& st) = delete;;SingelTon& operator=(const SingelTon& st) = delete;public:static T* GetInstance() {return &data;}
};
template<class T>
T Singleton::data = /**/;
//Singleton<T> Singleton::data = /**/;
吃完饭, 立刻洗碗, 这种就是饿汉方式. 因为下一顿吃的时候可以立刻拿着碗就能吃饭;也就是系统一运行,就初始化创建实例,当需要时,直接调用即可。这种方式本身就可以保证线程安全,没有多线程的线程安全问题
懒汉模式
懒汉模式注意的细节:
- 需要将构造函数,拷贝构造函数,赋值运行符重载函数屏蔽,防止在外部实例化对象。
- 在类中成员包含一个类对象指针,而不是对象。
- 类中写一个接口(静态),用户返回创建后的对象(但只能调用一次)
- 因为是需要时才会创建,所以需要考虑线程安全问题,保证多线程下只能创建一个对象
template <class T>
class Singleton
{volatile static T* inst; // 需要设置 volatile 关键字, 否则可能被编译器优化.static std::mutex lock;Singleton(){pthread_mutex_init(&lock,nullptr);}~Singleton(){pthread_mutex_destroy(&lock);}Singleton(const Singleton<T>& sl) = delete;Singleton<T>& operator=(Singleton<T> sl) = delete;public:static T* GetInstance() {if (inst == NULL) { // 双重判定空指针, 降低争锁冲突, 提高性能.lock.lock(); // 使用互斥锁, 保证多线程情况下也只调用一次 new.if (inst == NULL) {inst = new T();}lock.unlock();}return inst;}
};
//类外初始化静态成员
template <class T>
T* Singleton::inst = nullptr;
吃完饭, 先把碗放下, 然后下一顿饭用到这个碗了再洗碗, 就是懒汉方式;也就是系统运行中,实例并不存在,只有当需要使用该实例时,才会去创建并使用实例。这种方式要考虑线程安全问题
饿汉懒汉对比
饿汉模式
优点:
- 实现简单,不需要考虑线程安全问题。
缺点:
启动慢。如果实例的对象占用资源很多,在启动时需要加载。
如果多个单例类对象,在程序启动时实例对象的顺序不确定。如果对象之间有依赖关系,就麻烦了。
懒汉模式
优点:
启动快。在需要时才会实例化对象,加载资源。
多个单例类对象,实例化的顺序可以确定。取决于调用类的函数的顺序。
缺点:
- 实现复杂。需要考虑线程安全问题。
其他的锁
- 悲观锁:在每次取数据时,总是担心数据会被其他线程修改,所以会在取数据前先加锁(读锁,写锁,行 锁等),当其他线程想要访问数据时,被阻塞挂起。
- 乐观锁:每次取数据时候,总是乐观的认为数据不会被其他线程修改,因此不上锁。但是在更新数据前, 会判断其他数据在更新前有没有对数据进行修改。主要采用两种方式:版本号机制和CAS操作。
- CAS操作:当需要更新数据时,判断当前内存值和之前取得的值是否相等。如果相等则用新值更新。若不等 则失败,失败则重试,一般是一个自旋的过程,即不断重试。
相关文章:

Linux操作系统学习(线程池)
文章目录线程池线程池原理代码示例单例模式饿汉模式懒汉模式饿汉懒汉对比其他的锁线程池 线程池原理 线程池是一种线程使用模式。在多线程应用中,若每有一个任务,线程就去调度相应的函数去创建,当任务过多时,每次都去调度且每…...

JVM运行时数据区—Java虚拟机栈
虚拟机栈的背景 由于跨平台性的设计,java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的。 根据栈设计的优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功…...

gitlab中文社区
1、获取gitlab中文社区项目 中文社区版项目:https://gitlab.com/xhang/gitlab 2、克隆中文仓库 git clone https://gitlab.com/xhang/gitlab.git 3、查看gitlab版本 diff 获取对应版本的中文 head -1 /opt/gitlab/version-manifest.txt #安装的是gitlab-ce…...

深度学习-第T2周——彩色图片分类
深度学习-第T2周——彩色图片分类深度学习-第P1周——实现mnist手写数字识别一、前言二、我的环境三、前期工作1、导入依赖项并设置GPU2、导入数据集3、归一化4、可视化图片四、构建简单的CNN网络五、编译并训练模型1、设置超参数2、编写训练函数六、预测七、模型评估深度学习-…...

GNU C编译器扩展关键字:__attribute__
目录 一、section 二、aligned 三、packed 四、format 五、weak 六、alias 七、noinline和always_inline GNU C增加了一个__attribute__关键字用来声明一个函数、变量或类型的特殊属性,可以知道编译器在编译过程中进行特定方面的优化或代码检查。 目前&…...

C++基础 | 从C到C++快速过渡
一、开发环境 c使用的编译器是g。 vim或者vscodeclionVS 二、C版本的Hello World /*** brief c版本helloworld示例* author Mculover666* date 2023/2/26*/#include <iostream> using namespace std;int main() {int a 1;double b 3.14;char c[] "str…...

【C++】仿函数 -- priority_queue
文章目录一、priority_queue 的介绍和使用1、priority_queue 的介绍2、priority_queue 的使用3、priority_queue 相关 OJ 题二、仿函数1、什么是仿函数2、仿函数的作用三、priority_queue 的模拟实现一、priority_queue 的介绍和使用 1、priority_queue 的介绍 priority_queu…...

盘一盘C++的类型描述符(一)
前言 C的类型描述方式是从C语言继承来的,并且进行了扩充(例如引用、非静态成员函数、模板实参等)。但由于C语言中的类型描述方式就略微有点「反人类」,再经C扩展后就有点「反碳基生物」了~ 是的,当我第一次看到这种描…...

Peppol的发展史和基本框架
Peppol(Pan-European Public Procurement Online)是欧洲区域内的一个跨境公共采购电子商务平台试点项目,由欧盟委员会和Peppol联盟成员国共同资助建立,旨在通过制定标准化框架,推动欧盟成员国在公共采购相关的电子目录…...

Linux-GCC介绍+入门级Makefile使用
前言(1)我们都知道,在Linux中编译.c文件需要使用gcc -o .c文件的指令来将C文件变成可执行文件。但是我们有没有发现,如果我们需要编译大一点的工程,后面需要加上的.c文件是不是太多了?感觉非常的麻烦。&…...

iOS(一):Swift纯代码模式iOS开发入门教程
Swift纯代码模式iOS开发入门教程项目初始化(修改为纯代码项目)安装第三方库(以SnapKit库为例)桥接OC库(QMUIKit)封装视图并进行导航跳转示例:使用 TangramKit 第三方UI布局库应用国际化添加 R.s…...

IDEA+Python+Selenium+360浏览器自动化测试
环境配置前提,见文章https://mp.csdn.net/mp_blog/creation/editor/new?spm1001.2101.3001.4503下载360浏览器,并下载对应版本的chromedriver.exe,下载地址http://chromedriver.storage.googleapis.com/index.html下载好360浏览器࿰…...

运输层概述及web请求
运输层 运输层概述 运输层向高层用户屏蔽了下面网络核心的细节(如网络拓扑、所采用的路由选择协议等)它使应用进程看见的就好像是在两个运输层实体之间有一条端到端的逻辑通信信道; 根据需求不同,运输层提供两种运输协议 面向连…...

python与pycharm从零安装
python(解释器)下载地址:Welcome to Python.orgpycharm(编译器)下载地址:PyCharm: the Python IDE for Professional Developers by JetBrains一、python的下载与安装到官网后根据步骤下载安装包后…...

叠氮试剂943858-70-6,Azidobutyric acid NHS ester,叠氮-C3-活性酯
1、试剂基团反应特点(Reagent group reaction characteristics):Azidobutyric acid NHS ester具有叠氮化物和NHS酯端基。西安凯新生物科技有限公司供应的叠氮化物可以与炔烃、DBCO和BCN进行铜催化的点击化学反应。NHS酯可以与胺基反应&#x…...

pycharm激活虚拟环境时报错:无法加载文件activate.ps1,因为在此系统上禁止运行脚本,Windows10系统
问题: ii_env\Scripts\activate : 无法加载文件 F:\gitlab\AutoFrame\ii_env\Scripts\Activate.ps1,因为在此系统上禁止运行脚本。 有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_Execution_Policies。 所在…...

刷题小抄4-数组
在Python中数组的功能由列表来实现,本文主要介绍一些力扣上关于数组的题目解法 寻找数组中重复的数字 题目链接 题目大意: 给出一个数组,数组长度为n,数组里的数字在[0,n-1]范围以内,数字可以重复,寻找出数组中任意一个重复的数字,返回结果 解法一 该题最基础的思路是使用字…...

Hbase安装
目录 上传压缩包 解压 改名 修改 Hbase 配置文件 修改base-env.sh 修改hbase-site.xml 配置环境变量 修改zookeeper配置文件 复制配置文件 修改zoo.cfg配置文件 修改myid 配置环境变量 刷新配置文件 启动Hbase 进入Hbase 查看版本号 查看命名空间 查看命名空…...

面向对象设计模式:结构型模式之代理模式
一、引入 访问 FB:代理服务器 二、代理模式 aka Surrogate 2.1 Intent 意图 Provide a surrogate (代理) or placeholder for another object to control access to it. 为另一个对象提供一个代理或占位符,以控制对它的访问。代理模式给某一个对象提…...

CCF大数据专家委员会十周年纪念庆典纪实:拥抱数字时代,展望科技未来
山河远阔,奋进十年,作为国内大数据领域最权威的学术组织,CCF大数据专家委员会(以下简称“大专委”)不忘初心,凝心聚力,见证并推动了过去10年来大数据技术生态在中国的建立、发展和成熟。 2023年…...

Qt学习3-Qt Creator四则运算计算器(哔站视频学习记录)
计算器中的“”按钮这部分的代码解释 目录 制作计算器中的“”按钮这部分的代码解释 一、代码部分 二、解释 三、思路 四、死循环! 一、代码部分 void Widget::on_equalButton_clicked() {QStack<int> s_num,s_opt; //声明两个int类型变量char opt[128…...

学习 Python 之 Pygame 开发魂斗罗(九)
学习 Python 之 Pygame 开发魂斗罗(九)继续编写魂斗罗1. 在子弹类中修改敌人发射子弹的位置2. 创建显示敌人子弹的函数3. 解决敌人不会向下掉落的问题4. 给敌人碰撞体组增加碰撞体5. 解决敌人叠加在一起的问题继续编写魂斗罗 在上次的博客学习 Python 之…...

最简单的SpringBoot+MyBatis多数据源实现
最简单的SpringBootMyBatis多数据源实现1.数据库准备2.环境准备3.代码部分3.1多数据源配置2.测试随着应用用户数量的增加,相应的并发请求的数量也会跟着不断增加,慢慢地,单个数据库已经没有办法满足频繁的数据库操作请求了,在某些…...

Spring Boot 3.0系列【8】核心特性篇之SpringApplication
有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot版本3.0.3 源码地址:https://gitee.com/pearl-organization/study-spring-boot3 文章目录 前言1. 启动应用2. 自定义 Banner3. 应用参数传递参数获取参数4. ApplicationRunner、CommandLineRunner5. 事件发布和监听…...

Nginx的搭建与核心配置
目录 一.Nginx是什么? 1.Nginx概述 2.Nginx模块与作用 3.Nginx三大作用:反向代理、负载均衡、动静分离 二.Nginx和Apache的差异 三.安装Nginx 1.编译安装 2.yum安装 四.Nginx的信号使用 五.Nginx的核心配置指令 1.访问状态统计配置 2.基于授…...

Java学习笔记 --- jQuery
一、jQuery介绍 jQuery,顾名思义,也就是JavaScript和查询(Query),它就是辅助JavaScript开发的js类库。它的核心思想是write less,do more(写得更少,做得更多),…...

华为OD机试题,用 Java 解【字符串加密】问题
华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…...

软聚类算法:模糊聚类 (Fuzzy Clustering)
前言 如果你对这篇文章感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。 在介绍模糊聚类之前,我们先简单地列举一下聚类算法的常见分类: 硬聚类 (Hard Clustering) Connec…...

Java Web 实战 02 - 多线程基础篇(1)
Java Web 实战 02 - 多线程基础篇 - 1一 . 认识线程1.1 概念1.1.1 什么是线程?1.1.2 为什么要有多个线程?1.1.3 进程和线程的区别(面试题)1.2 第一个多线程程序1.3 创建线程1.3.1 继承Thread类1.3.2 实现Runnable接口1.3.3 继承 Thread 类 , 使用匿名内部类1.3.4 实现 Runnab…...

C/C++开发,无可避免的多线程(篇三).协程及其支持库
一、c20的协程概念 在c20标准后,在一些函数中看到co_await、co_yield、co_return这些关键词,这是c20为协程实现设计的运算符。 协程是能暂停执行以在之后恢复的函数。原来我们调用一个功能函数时,只要调用了以后,就要完整执行完该…...