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

【Linux】线程实例 | 简单线程池

今天来写一个简单版本的线程池

1.啥是线程池

池塘,顾名思义,线程池就是一个有很多线程的容器。

我们只需要把任务交到这个线程的池子里面,其就能帮我们多线程执行任务,计算出结果。

与阻塞队列不同的是,线程池中内有一个队列用于任务管理,并帮我们封装了线程创建的工作。我们不再需要在主执行流里面创建线程(创建线程也是有时间消耗的),而是只关注于任务的创建,交给线程池来运行并产生结果就OK了

前面已经学习过阻塞队列了,此时再来写线程池,就没有那么困难了!

本次线程池的设计还会采用单例模式,同一个模板类型的任务,只需要一个线程池即可

1.1 简单复习单例模式

单例模式分为两种设计方式,一个是懒汉,一个是饿汉

  • 懒汉:刚开始先不创建单例,等第一次使用的时候在创建;缺点是第一次获取单例需要等待,优点是程序启动快
  • 饿汉:main函数执行前,就将单例创建起来;缺点是程序启动会比较慢,优点是启动之后获取单例会快

2.代码示例-处理task

2.1 成员变量

因为是线程池,需要在内部创建出线程来运行,所以我们需要一个num来标识需要创建的线程的数量

template <class T>
class ThreadPool{
private:bool _isStart;  // 线程池子是否启动int _threadNum; // 线程数量queue<T> _tq;   // 任务队列pthread_mutex_t _mutex;// 锁pthread_cond_t _cond;  // 条件变量static ThreadPool<T> *instance; // 单例模式需要用到的指针
}

这里我们并不需要弄一个数组来存放已经创建的线程,因为我们并不关心线程的退出信息,也不需要对线程进行管理。在创建好线程之后,直接detach即可

static变量我们需要在类外初始化,因为是模板类型,所以还需要带上template关键字

// 初始化static变量
template <class T>
ThreadPool<T> *ThreadPool<T>::instance = nullptr;

2.2 构造/析构

本次使用的是懒汉模式的单例,提供一个指针作为单例,不开放构造函数

private:ThreadPool(int num = DEFALUT_NUM): _threadNum(num),_isStart(false){assert(num > 0);pthread_mutex_init(&_mutex, nullptr);pthread_cond_init(&_cond, nullptr);}ThreadPool(const ThreadPool<T> &) = delete;//取消拷贝void operator=(const ThreadPool<T> &) = delete;//取消赋值

同时,利用delete关键字,禁止拷贝构造和赋值重载;析构依旧保持公有

    ~ThreadPool(){pthread_mutex_destroy(&_mutex);pthread_cond_destroy(&_cond);}

这种情况下,我们还需要有一个static成员函数来获取单例;在之前的单例模式博客中,提到当初实现的懒汉模式是线程不安全的,因为没有对线程进行加锁,避免多个执行流同时获取单例,导致单例对象冲突的问题。

现在学习了linux的加锁操作,就可以避免掉这个bug了

两次nullptr判断

其中关于两次nullptr判断的原因,详见注释

  • 第一个判断是为了保证单例,只要单例存在了,就不再创建单例
  • 第二个判断是保证线程安全,可能会出现线程a在创建单例,线程b在锁中等待的情况;此时如果不进行第二次nullptr判断,线程b从锁中被唤醒后,又会继续执行,多创建了一个单例!
public:static ThreadPool<T> *getInstance(){static pthread_mutex_t mt;//使用static,只会创建一次;避免多次实例化,一个执行流一个锁,失去效果pthread_mutex_init(&mt,nullptr);if (instance == nullptr) // 第一次判断{pthread_mutex_lock(&mt);// 加锁,保证只有一个执行流走到这里if (instance == nullptr)// 第二次判断是来确认的,避免出现在加锁前,被其他执行流获取过实例了{instance = new ThreadPool<T>();// 确认是null,创建单例}}pthread_mutex_unlock(&mt);pthread_mutex_destroy(&mt);return instance;}

2.3 启动线程池

有了线程池,接下来要做的就是启动它😁

启动之前,我们需要assert判断一下该线程池是否已经启动了,避免多次启动线程池出现问题。启动完成之后,更新isStart的状态值

    void start(){assert(!_isStart);//如果开启了,那么就不能执行该函数for (int i = 0; i < _threadNum; i++){pthread_t temp;pthread_create(&temp, nullptr, threadRoutine, this);//把this当参数传入usleep(100);pthread_detach(temp);//分离线程}_isStart = true;//标识状态,代表线程池已经启动了}

这里还有另外一个函数threadRoutine,这是每一个线程需要执行的函数,其为static函数。这里我们获取到的都是单例的this指针,访问成员都需要通过this指针来访问

static void *threadRoutine(void *args)
{ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);//c++强转while (1){tp->lockQueue();while (!tp->haveTask()){tp->waitForTask();}// 任务被拿到了线程的上下文中T t = tp->pop();tp->unlockQueue();// 规定每一个封装的task对象都需要有一个run函数t.resultPrint(t.run());//运行并打印结果}
}

2.4 封装的加锁/解锁/通知操作

这部分操作比较简单,就不多提了。其实就是把已有的函数改个名字,变成无参可直接调用的函数罢了。

private:void lockQueue() { pthread_mutex_lock(&_mutex); }void unlockQueue() { pthread_mutex_unlock(&_mutex); }bool haveTask() { return !_tq.empty(); }void waitForTask() { pthread_cond_wait(&_cond, &_mutex); }void singalThread() { pthread_cond_signal(&_cond); }T pop(){T temp = _tq.front();_tq.pop();return temp;}

其中pop()函数设置为了私有,因为线程池会自己开始处理任务,所以不需要外部pop


2.5 插入任务

最后就只剩下任务的插入了,插入一个任务后,使用条件变量,唤醒线程池中的一个线程来执行这个任务!

    //往线程池中给任务void push(const T &in){lockQueue();_tq.push(in);//插入任务singalThread();//任务插入后,唤醒一个线程来执行unlockQueue();}

到这里,线程池就大功告成了!

3.测试

本次测试依旧使用了在线程博客中提到过的task.hpp,完整代码详见我的gitee仓库

因为使用了线程池,主执行流只需要来派发任务即可;

#include "threadpool.hpp"
#include "task.hpp"
#include <string>
#include <time.h>int main()
{const string operators = "+/*/%";ThreadPool<Task>*tp = ThreadPool<Task>::getInstance();tp->start();srand((unsigned long)time(nullptr) ^ getpid() ^ pthread_self());// 派发任务的线程while(1){int one = rand()%50;int two = rand()%10;char oper = operators[rand()%operators.size()];cout << "[" << pthread_self() << "] 主线程派发计算任务: " << one << oper << two << "=?" << "\n";Task t(one, two, oper);tp->push(t);sleep(1);}}

此时线程池就会帮我们运行,并将结果输出!

[muxue@bt-7274:~/git/linux/code/23-01-18 threadpool]$ ./test
[140202992179008] 主线程派发计算任务: 14/8=?
[140202973767424] 新线程完成计算任务: 14/8=1
[140202992179008] 主线程派发计算任务: 43*2=?
[140202965374720] 新线程完成计算任务: 43*2=86
[140202992179008] 主线程派发计算任务: 10/9=?
[140202956982016] 新线程完成计算任务: 10/9=1
[140202992179008] 主线程派发计算任务: 25*9=?
[140202948589312] 新线程完成计算任务: 25*9=225
[140202992179008] 主线程派发计算任务: 8/0=?
div zero, abort
[140202940196608] 新线程完成计算任务: 8/0=-1
[140202992179008] 主线程派发计算任务: 38%1=?
[140202973767424] 新线程完成计算任务: 38%1=0
[140202992179008] 主线程派发计算任务: 23/7=?
[140202965374720] 新线程完成计算任务: 23/7=3
[140202992179008] 主线程派发计算任务: 4%4=?
[140202956982016] 新线程完成计算任务: 4%4=0
[140202992179008] 主线程派发计算任务: 44*8=?
[140202948589312] 新线程完成计算任务: 44*8=352
[140202992179008] 主线程派发计算任务: 4/2=?

3.1 修改轻量级进程的名字

Linux提供了一个有趣的接口,可以允许我们修改轻量级进程的名字;

没有修改的时候,默认的名字都是该进程的可执行程序的名字

[muxue@bt-7274:~/git/linux/code/23-01-18 threadpool]$ ps -aLPID   LWP TTY          TIME CMD6592  6592 pts/7    00:00:00 test6592  6593 pts/7    00:00:00 test6592  6594 pts/7    00:00:00 test6592  6595 pts/7    00:00:00 test6592  6596 pts/7    00:00:00 test6592  6597 pts/7    00:00:00 test6730  6730 pts/8    00:00:00 ps

我们使用prctl接口,修改名字;这个接口的作用是对一个进程进行操作。

#include <sys/prctl.h>
int prctl(int option, unsigned long arg2, unsigned long arg3,unsigned long arg4, unsigned long arg5);

其中修改线程名字的操作如下

prctl(PR_SET_NAME, "handler");//修改线程名字为handler

分别修改主执行流和线程池中线程的名字,即可获得不一样的结果

[muxue@bt-7274:~/git/linux/code/23-01-18 threadpool]$ ps -aLPID   LWP TTY          TIME CMD7793  7793 pts/7    00:00:00 master7793  7794 pts/7    00:00:00 handler7793  7795 pts/7    00:00:00 handler7793  7796 pts/7    00:00:00 handler7793  7797 pts/7    00:00:00 handler7793  7798 pts/7    00:00:00 handler7828  7828 pts/8    00:00:00 ps

这样可以用于标识线程的属性,还是有些用的!

The end

本篇博客到这里就over啦,有啥问题欢迎评论区提出哦!

QQ图片20220413084241

相关文章:

【Linux】线程实例 | 简单线程池

今天来写一个简单版本的线程池 1.啥是线程池 池塘&#xff0c;顾名思义&#xff0c;线程池就是一个有很多线程的容器。 我们只需要把任务交到这个线程的池子里面&#xff0c;其就能帮我们多线程执行任务&#xff0c;计算出结果。 与阻塞队列不同的是&#xff0c;线程池中内有…...

ATAC-seq 数据分析实战

文章目录一、 ATAC-seq原理和基础知识1. ATAC-seq原理2. Tn5转座子1. 转座概念2. 参与分子1. 转座子&#xff08;1&#xff09; 简化的转座子结构&#xff08;2&#xff09; Tn5转座子的结构2. 转座酶3. 转座过程二、数据比对和过滤一、 ATAC-seq原理和基础知识 1. ATAC-seq原…...

设计模式-第13章(状态模式)

状态模式状态模式状态模式的好处和用处工作状态状态模式 状态模式&#xff08;State&#xff09;&#xff0c;当一个对象的内在状态改变时允许改变其行为&#xff0c;这个对象看起来像是改变了其类。 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况…...

ReentrantLock源码分析(一)加锁流程分析

一、ReetrantLock的使用示例 static ReentrantLock lock new ReentrantLock(); public static void main(String[] args) throws InterruptedException { new Thread(ClassLayOutTest::reentrantLockDemo, "threadA").start(); Thread.sleep(1000);…...

【C++】list的模拟实现

文章目录1.list 底层2. list的模拟实现1. list_node 类设计2. list类如何调用类型3 .push_back(正常实现)4. 迭代器的实现第一个模板参数Tconst迭代器第二个模板参数Ref第三个模板参数Ptr对list封装的理解5. insert6.push_back与 push_front(复用)7. erase8. pop_back与pop_fro…...

Python连接es笔记三之es更新操作

这一篇笔记介绍如何使用 Python 对数据进行更新操作。 对于 es 的更新的操作&#xff0c;不用到 Search() 方法&#xff0c;而是直接使用 es 的连接加上相应的函数来操作&#xff0c;本篇笔记目录如下&#xff1a; 获取连接update()update_by_query()批量更新UpdateByQuery()…...

哪个牌子的蓝牙耳机音质好?音质比较好的蓝牙耳机排名

蓝牙耳机经过多年发展&#xff0c;无论是在外观设计还是性能配置上都有很大的进步&#xff0c;越来越多的蓝牙耳机开始注重音质表现&#xff0c;逐渐有HIFI音质、无损音质出现在大众视野。那么哪个牌子的蓝牙耳机音质好&#xff1f;接下来&#xff0c;我来给大家分享几款音质比…...

Qt实用技巧:Qt中浮点数的相等比较方式(包括单精度和双精度)

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/129464152 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…...

【数据结构初阶】双向循环链表

目录一.链表的分类二.与单链表相比三.实现增删查改1.双向循环链表结构的创建2.创建新节点3.初始化链表4.头插和尾插5.判断链表是否为空6.头删和尾删7.打印函数8.查找函数9.删除pos位置节点10.在pos前位置插入数据11.优化升级一.链表的分类 链表可有根据单向双向、有无哨兵位、…...

0104BeanDefinition合并和BeanClass加载-Bean生命周期详解-spring

文章目录1 前言2 BeanDefinition合并2.1 BeanDefinition合并在做什么&#xff1f;2.2 BeanDefinition怎么合并2.3 示例演示3 Bean Class 加载后记1 前言 下面要介绍的阶段&#xff0c;都是在调用getBean()从容器中获取bean对象的过程中发生的操作&#xff0c;我们需要更多的去…...

Java集合进阶(三)

文章目录一、Map1. 概述2. 基本功能3. 遍历4. 遍历学生对象5. 集合嵌套6. 统计字符出现次数二、Collections1. 常用方法2. 学生对象排序三、模拟斗地主一、Map 1. 概述 Interface Map<K, V>&#xff1a;K 是键的类型&#xff0c;V 是值的类型。 将键映射到值的对象&…...

【网络】什么是RPC?RPC与HTTP有什么关系?

文章目录RPC是什么RPC和HTTP的关系和区别[附]关于REST论文中提到的"HTTP不是RPC"重点参考 凤凰架构-远程过程调用 既然有HTTP为什么还要有RPC&#xff1f; RPC是什么 RPC(Remote Procedure Call)&#xff1a;即远程过程调用&#xff0c;目的是为了让计算机能够跟调用…...

[手撕数据结构]栈的深入学习-java实现

CSDN的各位uu们你们好,今天千泽带来了栈的深入学习,我们会简单的用代码实现一下栈, 接下来让我们一起进入栈的神奇小世界吧!0.速览文章一、栈的定义1. 栈的概念2. 栈的图解二、栈的模拟实现三.栈的经典使用场景-逆波兰表达式总结一、栈的定义 1. 栈的概念 栈&#xff1a;一种…...

2.线性表的顺序表示

数据结构很重要&#xff01; 数据结构很重要&#xff01;&#xff01;&#xff01; 数据结构很重要&#xff01;&#xff01;&#xff01;&#xff01; 思考 1.线性表的顺序表示内容有哪些&#xff1f;&#xff08;What&#xff09; 2.为什么要学线性表的顺序表示? ? (Why)…...

eps文件删除了能恢复吗?恢复误删eps文件的三种方法

eps文件格式专为矢量图像和图形而设计。虽然没有被广泛使用&#xff0c;但它仍然受到各种插画家和平面设计师的钟爱。eps文件十分适合创建徽标和商标设计&#xff0c;主要应用见于广告牌、海报和横幅。可是在使用设备过程中&#xff0c;难免会遇到数据丢失问题&#xff0c;如果…...

【C++】运算符重载练习——Date 类

文章目录&#x1f449;日期类介绍&#x1f448;&#x1f449;日期类实现&#x1f448;&#x1f4d5; 成员变量&#x1f4d5; 构造函数&#x1f4d5; 对应月份天数&#x1f4d5; 赋值重载&#x1f4d5; 比较运算符重载&#x1f4d5; 计算 运算符重载&#x1f449;源代码&#x1…...

Redis学习(13)之Lua脚本【环境准备】

文章目录一 Lua入门环境准备1.1 Lua简介1.2 Linux 系统安装Lua1.2.1 Lua 下载1.2.2 Lua 安装1.3 Hello World1.3.1 命令行模式1.3.2 脚本文件模式1.3.3 两种脚本运行方式1.4 Win安装Lua1.4.1 LuaForWindows的安装1.4.2 SciTE修改字体大小1.4.3 SciTE中文乱码1.4.4 SciTE快捷键工…...

关于BLE的一些知识总结

数据包长度对于BLE4.0/4.1来说&#xff0c;一个数据包的有效载荷最大为20字节对于BLE4.2以上&#xff0c;数据包的有效载荷扩大为251字节传输速率在不考虑跳频间隔的情况下&#xff0c;最大传输速率为&#xff1a;1&#xff09;BLE4.0/4.1的理论吞吐率为39kb/s&#xff1b;2&am…...

Spring框架源码分析一

如何看源码&#xff08;方法论&#xff09;不要忽略源码中的注释使用翻译工具先梳理脉络&#xff0c;然后梳理细节即总分总&#xff0c;先总体过一遍&#xff0c;再看细节&#xff0c;再做一个总结大胆猜测&#xff08;8分靠猜&#xff09;&#xff0c;小心验证&#xff0c;再调…...

CSS常用内容总结(扫盲)

文章目录前言相关概念【了解】脚本语言什么是脚本语言脚本语言有什么特点常见的脚本语言什么是动态语言&#xff0c;什么是静态语言动态语言和静态语言两者之间有何区别CSSCSS是什么CSS的特点一、CSS代码怎么写基本语法规则引入方式内部样式内联样式表外部样式代码风格二、CSS的…...

Java启蒙之语言基础

目录 一.Java标识符和关键字 1.1Java标识符 1.2Java关键字 二.数据类型和变量的概述和关系 2.1Java变量 2.2Java的数据类型 2.2.1数据类型的分类的概述 2.2.2数据类型的转换 3.Java运算符 总结 &#x1f63d;个人主页&#xff1a;tq02的博客_CSDN博客-领域博主 &#…...

数据库系统--T-SQL数据查询功能-多表查询(超详细/设计/实验/作业/练习)

目录课程名&#xff1a;数据库系统内容/作用&#xff1a;设计/实验/作业/练习学习&#xff1a;T-SQL数据查询功能-多表查询一、前言二、环境与设备三、内容四、内容练习题目&#xff1a;对应题目答案&#xff1a;五、总结课程名&#xff1a;数据库系统 内容/作用&#xff1a;设…...

Spring Boot 3.0系列【14】核心特性篇之Configuration相关注解汇总介绍

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot版本3.0.3 源码地址:https://gitee.com/pearl-organization/study-spring-boot3 文章目录 前言@Configuration@ConfigurationProperties@EnableConfigurationProperties@ConfigurationPropertiesScan@Configuratio…...

[ubuntu][jetson]给jetson增加swap空间类似于给windows加虚拟内存

具体操作如下&#xff1a; #打开性能模式 sudo nvpmodel -m 0 && sudo jetson_clocks #增加swap空间&#xff0c;防止爆内存 swapoff -a sudo fallocate -l 15G /swapfile sudo chmod 600 /var/swapfile sudo mkswap /swapfile sudo swapon /swapfile…...

小黑子—Java从入门到入土过程:第二章

Java零基础入门2.0Java系列第二章1. 注释和关键字2. 字面量3. 变量3.1 基本用法3.2 使用方式3.3 注意事项4. 变量练习5. 计算机中的数据存储5.1 计算机的存储规则5.2 进制5.3 进制间转换二进制转十八进制转十十六进制转十十进制转其他进制6. 数据类型7. 定义变量的练习8. 标识符…...

ElasticSearch搜索详细讲解与操作

全文检索基础 全文检索流程 流程&#xff1a; #mermaid-svg-7Eg2qFEl06PIEAxZ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-7Eg2qFEl06PIEAxZ .error-icon{fill:#552222;}#mermaid-svg-7Eg2qFEl06PIEAxZ .error…...

web实现太极八卦图、旋转动画、定位、角度、坐标、html、css、JavaScript、animation

文章目录前言1、html部分2、css部分3、JavaScript部分4、微信小程序演示前言 哈哈 1、html部分 <div class"great_ultimate_eight_diagrams_box"><div class"eight_diagrams_box"><div class"eight_diagrams"><div class&…...

【LeetCode】33. 搜索旋转排序数组、1290. 二进制链表转整数

作者&#xff1a;小卢 专栏&#xff1a;《Leetcode》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 目录 33. 搜索旋转排序数组 1290. 二进制链表转整数 33. 搜索旋转排序数组 33. 搜索旋转排序…...

IBM Semeru Windows 下的安装 JDK 17

要搞清楚下载那个版本&#xff0c;请参考文章&#xff1a;来聊聊 OpenJDK 和 JVM 虚拟机下载地址semeru 有认证版和非认证版&#xff0c;主要是因为和 OpenJ9 的关系和操作系统的关系而使用不同的许可证罢了&#xff0c;本质代码是一样的。在 Windows 下没有认证版&#xff0c;…...

Lambda表达式和steram流

目录 引言&#xff1a; 语法: Lambda 表达式实例&#xff1a; demo演示&#xff1a; Stream流&#xff1a; 引言&#xff1a; Lambda 表达式&#xff0c;也可称为闭包&#xff0c;它是推动 Java 8 发布的最重要新特性。 Lambda 允许把函数作为一个方法的参数&#xff08;函…...

面试必会-MySQL篇

1. Mysql查询语句的书写顺序Select [distinct ] <字段名称>from 表1 [ <join类型> join 表2 on <join条件> ]where <where条件>group by <字段>having <having条件>order by <排序字段>limit <起始偏移量,行数>2. Mysql查询语…...

Hadoop入门常见面试题与集群时间同步操作

目录 一&#xff0c;常用端口号 Hadoop3.x &#xff1a; Hadoop2.x&#xff1a; 二&#xff0c;常用配置文件&#xff1a; Hadoop3.x: Hadoop2.x: 集群时间同步&#xff1a; 时间服务器配置&#xff08;必须root用户&#xff09;&#xff1a; &#xff08;1&#xff09…...

JS 数组去重的方法

// 数组去重 const arr ["1", "1", "2", "3", "5", "3", "1", "5", "4"] console.log(this.deduplicate(arr)) // [1, 2, 3, 5, 4] // 数组对象去重 const arr [ { id: 1, nam…...

PMP项目管理项目沟通管理

目录1 项目沟通管理2 规划沟通管理3 管理沟通4 监督沟通1 项目沟通管理 项目沟通管理包括通过开发工件&#xff0c;以及执行用于有效交换信息的各种活动&#xff0c;来确保项目及其相关方的信息需求得以满足的各个过程。项目沟通管理由两个部分组成&#xff1a;第一部分是制定…...

2.JVM常识之 运行时数据区

1.JVM核心组成 2.JVM 运行时数据区&#xff08;jdk8&#xff09; 程序计数器&#xff1a;线程私有&#xff0c;当前线程所执行字节码的行号指示器 jvm栈&#xff1a;线程私有&#xff0c;Java 虚拟机栈为 JVM 执行 Java 方法服务 本地方法栈&#xff1a;线程私有&#xff0c;本…...

你的游戏帐号是如何被盗的

据报道&#xff0c;2022上半年&#xff0c;中国游戏市场用户规模达到了5.54亿人&#xff0c;游戏市场销售收入1163.1亿元&#xff0c;相较去年均为同比增长的情况。如此庞大的市场规模&#xff0c;黑色产业链是绕不开的话题。 但相较于游戏中大家常见的玩家与玩家、玩家与官方…...

C++11异步编程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言1、std::future和std::shared_future1.1 std:future1.2 std::shared_future2、std::async3、std::promise4、std::packaged_task前言 C11提供了异步操作相关的类…...

20230310----重返学习-DOM元素的操作-时间对象-定时器

day-024-twenty-four-20230310-DOM元素的操作-时间对象-定时器 复习 获取元素 id document.getElementById() 类名 document.getElementsByClassName() 标签名 document.getElementsByTagName() name属性 document.getElementsByName() 选择器 document.querySelector()docum…...

江苏专转本转本人后悔排行榜

江苏专转本转本人后悔排行榜 一、复习的太迟&#xff1a; 后悔指数:五颗星。 复习越到最后&#xff0c;时间一天天变少&#xff0c;要复习的内容还有很多&#xff0c;很多人都后悔没有早早开始&#xff0c;总想着多给我两月一定会考上的。 担心时间不够用&#xff0c;那就努力利…...

【算法时间复杂度】学习记录

最近开算法课&#xff0c;开几篇文章记录一下算法的学习过程。 关于算法的重要性 学习计算机当程序员的话&#xff0c;在编程过程中是绕不开算法这个大矿山的&#xff0c;需要我们慢慢挖掘宝藏。 算法&#xff08;Algorithm&#xff09;是指用来操作数据、解决程序问题的一组…...

汽车车机芯片Linux系统内核编译问题总结

谈到车机,很多人会想到华为问界上装的大屏车机,号称车机的天花板,基于鸿蒙OS的,而今天谈到的车机芯片用的是linux内核Kernel,对于它的编译,很多人一时会觉得头大,的确如果工具不是很齐全,就会遇到这样那样的问题,但是过程都会有错误提示,按照错误提示基本可以解决,而…...

Android13 音量曲线调整

Android13 音量曲线调整 Android13 上配置文件的路径&#xff1a; /vendor/sprd/modules/audio/engineconfigurable_apm/工程目录/system/etc/audio_engine_config/audio_policy_engine_stream_volumes.xml /vendor/sprd/modules/audio/engineconfigurable_apm/工程目录/sys…...

OpenHarmony通过MQTT连接 “改版后的华为IoT平台”

一、前言 本篇文章我们使用的是BearPi-HM_Nano开发板:小熊派的主板+E53_IA1扩展板 源码用的是D6_iot_cloud_oc,点击下载BearPi-HM_Nano全量源码 那么为什么要写这篇呢? 前段时间看到OpenHarmony群里,经常有小伙伴问接入华为IoT平台的问题,他们无法正常连接到华为IoT平台等…...

SQS (Simple Queue Service)简介

mazon Simple Queue Service (SQS)是一种完全托管的消息队列服务&#xff0c;可以让你分离和扩展微服务、分布式系统和无服务应用程序。 在讲解SQS之前&#xff0c;首先让我们了解一下什么是消息队列。 消息队列 还是举一个电商的例子&#xff0c;一个用户在电商网站下单后付…...

高速PCB设计指南系列(三)

第一篇 高密度(HD)电路的设计 本文介绍&#xff0c;许多人把芯片规模的&#xff22;&#xff27;&#xff21;封装看作是由便携式电子产品所需的空间限制的一个可行的解决方案&#xff0c;它同时满足这些产品更高功能与性能的要求。为便携式产品的高密度电路设计应该为装配工艺…...

【C++】C++11——左右值|右值引用|移动语义|完美转发

文章目录一、左值与右值1.概念2.引用3.注意二、右值引用的意义1.左值引用意义2.右值引用和移动语义3.容器新增三、万能引用四、完美转发一、左值与右值 1.概念 左值是什么&#xff1f;右值是什么&#xff1f; 左值是一个表示数据的表达式&#xff08;如变量名或解引用的指针&…...

[ROC-RK3399-PC Pro] 手把手教你移植主线Buildroot(基于2023.02-rc3版本)

&#x1f347; 博主主页&#xff1a;Systemcall小酒屋&#x1f347; 博主简介&#xff1a;Neutionwei&#xff0c;C站嵌入式领域新星创作者之一&#xff0c;一枚热爱开源技术、喜欢分享技术心得的极客&#xff0c;注重简约风格&#xff0c;热衷于用简单的案例讲述复杂的技术&am…...

重温线性代数

前言 对于普通的数学工作者而言&#xff0c;掌握矩阵、线性空间的基本性质和用法比领会抽象的概念更实用。数学专业的同学需要全面深入学习近世代数的理论和演绎法则&#xff0c;例如模的概念和运算。 总之&#xff0c;我个人认为&#xff0c;不论是微积分、还是线性代数&…...

2023河北沃克HEGERLS甘肃金昌重型仓储项目案例|托盘式四向穿梭车智能密集存储系统在工业行业的创新应用

项目名称&#xff1a;自动化仓储托盘式四向穿梭车智能密集立体库项目 项目合作客户&#xff1a;甘肃省金昌市某集团企业 项目施工地域&#xff1a;甘肃省金昌市 设计与承建单位&#xff1a;河北沃克金属制品有限公司&#xff08;自主品牌&#xff1a;海格里斯HEGERLS&#x…...

软件测试的案例分析 - 闰年5

文章目的 显示不同的博客能获得多少博客质量分 &#xff08;这是关于博客质量分的测试 https://www.csdn.net/qc) 这个博客得了 83 分。怎么才能得到更多分数&#xff1f; 正文 我们谈了不少测试的名词, 软件是人写的, 测试计划和测试用例也是人写的, 人总会犯错误。错误发生…...