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

Linux操作系统7- 线程同步与互斥7(RingQueue环形队列生产者消费者模型改进)

上篇文章:Linux操作系统7- 线程同步与互斥6(POSIX信号量与环形队列生产者消费者模型)-CSDN博客

本篇代码仓库:myLerningCode/l36 · 橘子真甜/Linux操作系统与网络编程学习 - 码云 - 开源中国 (gitee.com)

目录

一. 单生产单消费单保存模型

1.1 RingQueue.hpp

1.2 Task.hpp

1.3 MainPC.cpp

1.4 测试

二. 多生产多消费模型        

2.1 分析与代码 

2.2 多生产多消费的意义


一. 单生产单消费单保存模型

        通过RingQueue可以实现生产者消费者之间的协同工作,如果现在想要将消费者的输出结果保存在文件中应该怎么办?

        可以定义两个环形队列,三个线程。让消费者充当第二个队列的生产者。

代码如下:

1.1 RingQueue.hpp

        直接使用上篇文件的代码即可。然后我们需要新增一个类,这个类中包含两个环形队列用于消费者同时访问两个队列

#pragma once
#include <iostream>
#include <vector>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
const int gnum = 10; // 阻塞队列的最大容量template <class T>
class RingQueue
{
private:void P(sem_t &sem){// P操作,申请信号量sem--int n = sem_wait(&sem);if (n < 0)std::cerr << "P操作失败" << std::endl;}void V(sem_t &sem){// V操作,释放信号量,sem++int n = sem_post(&sem);if (n < 0)std::cerr << "V操作失败" << std::endl;}public:RingQueue(const int &maxnum = gnum) : _maxnum(maxnum), _ringQueue(gnum){// 在构造函数中完成信号量的初始化int n = sem_init(&_spaceSem, 0, maxnum);if (n < 0)std::cerr << "spaceSem信号量初始化失败" << std::endl;n = sem_init(&_dataSem, 0, 0);if (n < 0)std::cerr << "dataSem信号量初始化失败" << std::endl;_producerStep = _consumerStep = 0;}~RingQueue(){sem_destroy(&_spaceSem);sem_destroy(&_dataSem);}// 生产者插入数据void push(const T &in){// 申请空间资源P(_spaceSem);// 插入数据_ringQueue[_producerStep++] = in;_producerStep %= _maxnum;// 释放一个数据资源V(_dataSem);}// 消费者获取数据void pop(T *out){// 申请数据资源P(_dataSem);// 插入数据*out = _ringQueue[_consumerStep++];_consumerStep %= _maxnum;// 释放一个空间资源V(_spaceSem);}private:std::vector<T> _ringQueue; // 使用数组来实现环形队列size_t _maxnum;sem_t _spaceSem; // 生产者空间资源信号量sem_t _dataSem;  // 消费者数据资源信号量int _producerStep; // 生产者下标int _consumerStep; // 消费者下标
};

1.2 Task.hpp

        需要新增一个保存者的任务

#pragma once
#include <iostream>
#include <cstdio>
#include <functional>class CalTask
{using func_t = std::function<int(int, int, char)>; // func是一个函数// typedef std::function<int(int,int)> func;
public:CalTask() {}CalTask(int x, int y, char op, func_t func): _x(x), _y(y), _op(op), _callback(func) {}std::string operator()(){int result = _callback(_x, _y, _op);char buffer[1024];snprintf(buffer, sizeof(buffer) - 1, "%d %c %d = %d", _x, _op, _y, result);return buffer;}// 返回任务操作的结果std::string toString(){char buffer[1024];snprintf(buffer, sizeof(buffer) - 1, "%d %c %d = ?", _x, _op, _y);return buffer;}private:int _x;int _y;char _op;         // 操作的任务的idfunc_t _callback; // 调用的函数
};class SaveTask
{typedef std::function<void(const std::string &)> func_t;public:SaveTask() {}SaveTask(const std::string &message, func_t func): _message(message), _callback(func) {}void operator()(){_callback(_message);}private:std::string _message; // 保存的信息func_t _callback;     // 将信息写入文件中
};const std::string oper = "+-*/%";
int my_math(int x, int y, char op)
{int result = 0;switch (op){case '+':result = x + y;break;case '-':result = x - y;break;case '*':result = x * y;break;case '/':{if (y == 0){std::cerr << "div zero" << std::endl;return -1;}else{result = x / y;}break;}case '%':if (y == 0){std::cerr << "moved zero" << std::endl;return -1;}else{result = x % y;}break;default:break;}return result;
}void Save(const std::string &message)
{const std::string task_pwd = "./log.txt";FILE *fp = fopen(task_pwd.c_str(), "a+");if (nullptr == fp){std::cerr << "saver open error" << std::endl;return;}fputs(message.c_str(), fp);fputc('\n', fp);fclose(fp);
}

1.3 MainPC.cpp

#include "RingQueue.hpp"
#include "Task.hpp"
#include <iostream>// 生产者
void *ProductorRoutine(void *args)
{RingQueue<CalTask> *cal_rq = (static_cast<RingQueues<CalTask, SaveTask> *>(args))->_cal_rq;while (true){int x = rand() % 20;int y = rand() % 50;const char op = oper[rand() % oper.size()];CalTask ct(x, y, op, my_math);cal_rq->push(ct);std::cout << "生产者生产任务:" << ct.toString() << " 并传递给消费者完成" << std::endl;}
}// 消费者
void *ConsumerRoutine(void *args)
{RingQueue<CalTask> *cal_rq = (static_cast<RingQueues<CalTask, SaveTask> *>(args))->_cal_rq;RingQueue<SaveTask> *save_rq = (static_cast<RingQueues<CalTask, SaveTask> *>(args))->_save_rq;while (true){CalTask ct;cal_rq->pop(&ct);std::string result = ct();std::cout << "消费者实现任务:" << result << " 实现完成!" << std::endl;SaveTask st(result, Save);save_rq->push(st);std::cout << "消费者传递任务:" << result << " 给保存者完成!" << std::endl;}
}// 保存者
void *SaverRoutine(void *args)
{RingQueue<SaveTask> *save_rq = (static_cast<RingQueues<CalTask, SaveTask> *>(args))->_save_rq;while (true){SaveTask st;save_rq->pop(&st);st();std::cout << "保存者保存任务完成!" << std::endl;}
}void test1()
{RingQueues<CalTask, SaveTask> *rqs = new RingQueues<CalTask, SaveTask>;rqs->_cal_rq = new RingQueue<CalTask>();rqs->_save_rq = new RingQueue<SaveTask>();pthread_t p, c, s;pthread_create(&p, nullptr, ProductorRoutine, rqs);pthread_create(&c, nullptr, ConsumerRoutine, rqs);pthread_create(&s, nullptr, SaverRoutine, rqs);pthread_join(p, nullptr);pthread_join(c, nullptr);pthread_join(s, nullptr);delete rqs;
}int main()
{srand((unsigned int)time(0) ^ getpid() ^ pthread_self());test1();return 0;
}

1.4 测试

        运行结果如下:

二. 多生产多消费模型        

2.1 分析与代码 

        RingQueue环形队列可以保证单个生产者和单个消费者之间的同步与互斥,如果现在有多个生产者和多个消费者的话。如何保证生产者之间的互斥?消费者者之间的互斥?

        阻塞队列中,我们通过加锁的方式让同一时刻只能有一个生产者线程进入临界区或者一个消费者进入临界区。

        而环形队列中, 通过信号量保证了生产者消费者之间的同步与互斥。如果想要保证消费者与消费者之间的互斥,生产者与生产者之间的互斥,也需要加锁保护

        在RingQueue中添加两个成员变量,一个生产者互斥锁,一个消费者互斥锁。同时需要在构造函数中完成锁的初始化,析构函数中完成锁的销毁。

        并且在push函数中加生产者锁,在pop函数中加消费者锁。以实现生产者与生产者之间的互斥和消费者与消费者之间的互斥。(本质是防止多个线程同时访问导致生产者下标或者消费者下标出现数据错误) 

代码如下:

#pragma once
#include <iostream>
#include <vector>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
const int gnum = 10; // 阻塞队列的最大容量template <class T>
class RingQueue
{
private:void P(sem_t &sem){// P操作,申请信号量sem--int n = sem_wait(&sem);if (n < 0)std::cerr << "P操作失败" << std::endl;}void V(sem_t &sem){// V操作,释放信号量,sem++int n = sem_post(&sem);if (n < 0)std::cerr << "V操作失败" << std::endl;}public:RingQueue(const int &maxnum = gnum) : _maxnum(maxnum), _ringQueue(gnum){// 在构造函数中完成信号量的初始化int n = sem_init(&_spaceSem, 0, maxnum);if (n < 0)std::cerr << "spaceSem信号量初始化失败" << std::endl;n = sem_init(&_dataSem, 0, 0);if (n < 0)std::cerr << "dataSem信号量初始化失败" << std::endl;_producerStep = _consumerStep = 0;// 初始化锁pthread_mutex_init(&_pmtx, nullptr);pthread_mutex_init(&_cmtx, nullptr);}~RingQueue(){// 销毁信号量与互斥锁sem_destroy(&_spaceSem);sem_destroy(&_dataSem);//pthread_mutex_destroy(&_cmtx);pthread_mutex_destroy(&_pmtx);}// 生产者插入数据void push(const T &in){// 生产者加锁,保证生产者与生产者之间的互斥pthread_mutex_lock(&_pmtx);// 申请空间资源P(_spaceSem);// 插入数据_ringQueue[_producerStep++] = in;_producerStep %= _maxnum;// 释放一个数据资源V(_dataSem);// 解锁pthread_mutex_unlock(&_pmtx);}// 消费者获取数据void pop(T *out){// 消费者加锁pthread_mutex_lock(&_cmtx);// 申请数据资源P(_dataSem);// 插入数据*out = _ringQueue[_consumerStep++];_consumerStep %= _maxnum;// 释放一个空间资源V(_spaceSem);// 解锁pthread_mutex_unlock(&_cmtx);}private:std::vector<T> _ringQueue; // 使用数组来实现环形队列size_t _maxnum;sem_t _spaceSem; // 生产者空间资源信号量sem_t _dataSem;  // 消费者数据资源信号量int _producerStep; // 生产者下标int _consumerStep; // 消费者下标pthread_mutex_t _pmtx;pthread_mutex_t _cmtx;
};

MainPC.cpp

#include <iostream>
#include <memory>
#include <string>#include <unistd.h>
#include <pthread.h>
#include "RingQueue.hpp"
#include "Task.hpp"const std::string OP = "+-*/%";
void *producer(void *args)
{// 获取交易场所 - 阻塞队列RingQueue<CalTask> *rq = static_cast<RingQueue<CalTask> *>(args);while (true){int x = rand() % 100;int y = rand() % 100;char op = OP[rand() % OP.size()];// 打印日志printf("生产者生产的数据:%d %c %d 并交给消费者计算\n", x, op, y);CalTask ct(x, y, op, my_math);rq->push(ct);}return nullptr;
}void *consumer(void *args)
{// 获取交易场所 - 生产消费阻塞队列,消费保存阻塞队列RingQueue<CalTask> *rq = static_cast<RingQueue<CalTask> *>(args);while (true){// 获取任务计算CalTask ct;rq->pop(&ct);std::string result = ct();std::cout << "消费者获取数据并计算:" << result << std::endl;}return nullptr;
}int main()
{srand((unsigned int)time(0) ^ getpid());// 建立任务队列和保存队列RingQueue<CalTask> *rq = new RingQueue<CalTask>;pthread_t c[3], p[3];pthread_create(&c[0], nullptr, consumer, (void *)rq);pthread_create(&c[1], nullptr, consumer, (void *)rq);pthread_create(&c[2], nullptr, consumer, (void *)rq);pthread_create(&p[0], nullptr, producer, (void *)rq);pthread_create(&p[1], nullptr, producer, (void *)rq);pthread_create(&p[2], nullptr, producer, (void *)rq);pthread_join(c[0], nullptr);pthread_join(c[1], nullptr);pthread_join(c[2], nullptr);pthread_join(p[0], nullptr);pthread_join(p[1], nullptr);pthread_join(p[2], nullptr);delete rq;return 0;
}

测试结果如下:

可以看到,长时间没有出错

如果将加锁解锁操作进行注释:

会出现段错误,因为访问了非法内存

2.2 优化加解锁

        我们申请信号量和释放信号量是原子操作,不需要加锁解锁。无需将这个两个代码放入到临界区。并且一个线程在加锁期间,其他线程是可以申请信号量的!

    // 生产者插入数据void push(const T &in){// 申请空间资源P(_spaceSem);// 生产者加锁,保证生产者与生产者之间的互斥pthread_mutex_lock(&_pmtx);// 插入数据_ringQueue[_producerStep++] = in;_producerStep %= _maxnum;// 解锁pthread_mutex_unlock(&_pmtx);// 释放一个数据资源V(_dataSem);}// 消费者获取数据void pop(T *out){// 申请数据资源P(_dataSem);// 消费者加锁pthread_mutex_lock(&_cmtx);// 插入数据*out = _ringQueue[_consumerStep++];_consumerStep %= _maxnum;// 解锁pthread_mutex_unlock(&_cmtx);// 释放一个空间资源V(_spaceSem);}

        一样一来,一个线程加锁进入临界区之后不会去影响其他线程申请信号量。从而提高整体的效率。 

2.3 多生产多消费的意义

        与阻塞队列BlockQueue一样,多生产多消费的时候。生产线程生产数据可能需要很多时间,一个生产者生产者访问环形队列的时候不妨碍其他线程生产自己的资源。一个消费者访问环形队列拿数据的时候不妨碍其他消费者拿到数据进行处理

相关文章:

Linux操作系统7- 线程同步与互斥7(RingQueue环形队列生产者消费者模型改进)

上篇文章&#xff1a;Linux操作系统7- 线程同步与互斥6&#xff08;POSIX信号量与环形队列生产者消费者模型&#xff09;-CSDN博客 本篇代码仓库&#xff1a;myLerningCode/l36 橘子真甜/Linux操作系统与网络编程学习 - 码云 - 开源中国 (gitee.com) 目录 一. 单生产单消费单保…...

学有所记——初探向量数据库Weaviate

目标&#xff1a; 了解向量数据库的连接、建库、插入数据、查询数据等基本用法以及关于语义相似度的一些基本概念。 背景&#xff1a; 前段时间尝试在自己的电脑上搭建OllamaDify平台&#xff0c;体验并探索大模型的强大功能。在使用过程中&#xff0c;尤其是在搭建RAG知识库…...

Ardupilot开源无人机之Geek SDK进展2025Q2

Ardupilot开源无人机之Geek SDK进展2025Q2 1. 源由2. 内容汇总2.1 【jetson-fpv】“Caution - Hot surface. Dont touch.”2.2 【jetson-fpv】1080P/720P显示设备配置 3. 遗留问题3.1 高优先级3.1.1 【jetson-fpv】1080P60FPS AI分析视频卡顿&#xff0c;丢包3.1.2 【jetson-fp…...

深入理解K8s与Docker的关系:容器化技术的双雄

友情提示&#xff1a;本文内容由银河易创&#xff08;https://ai.eaigx.com&#xff09;AI创作平台gpt-4-turbo模型生成&#xff0c;仅供参考。 在现代云计算及微服务架构的发展中&#xff0c;Docker与Kubernetes&#xff08;K8s&#xff09;作为两大核心技术&#xff0c;被广泛…...

QT高效文件I/O编程--实用指南与最佳实践

概述 在软件开发过程中,文件输入输出(I/O)操作是数据持久化和交换的核心部分。无论是简单的日志记录还是复杂的数据集处理,高效的文件I/O操作对于应用的整体性能至关重要 最佳实践 一、选择合适的文件模式 正确选择文件打开模式是确保操作意图明确且安全的第一步。不同…...

QT记事本

记事本应用程序提供了基本的文本编辑功能&#xff0c;支持文件的新建、打开、保存和另存为操作&#xff0c;同时具备修改提示和关闭窗口时的保存确认功能。使用 UTF - 8 编码确保了对多语言文本的支持。 1. 项目整体结构 main.cpp&#xff1a;程序的入口点&#xff0c;负责初…...

【leetcode hot 100 84】柱状图中最大的矩形

解法一&#xff1a;单调栈 class Solution {public int largestRectangleArea(int[] heights) {int len heights.length;int area 0;// 先做一些特殊判断if(len0){return 0;}if(len1){return heights[0];}// 进入栈后发现后面更短&#xff0c;可以得到当前这个能勾勒的面积 …...

Spring----ioc

1.Spring 是什么&#xff1f; 通过前⾯的学习, 我们知道了Spring是⼀个开源框架, 他让我们的开发更加简单. 他⽀持⼴泛的应⽤场景, 有着活跃⽽庞⼤的社区, 这也是Spring能够⻓久不衰的原因. 但是这个概念相对来说, 还是⽐较抽象. 我们⽤⼀句更具体的话来概括Spring, 那就…...

C++——重载

目录 一、函数重载 基本概念 函数重载的条件 编程示例 代码讲解 函数重载的注意事项 二、运算符重载 什么是运算符重载&#xff1f; 运算符重载的实质是什么&#xff1f; 运算符重载函数的写法 运算符重载的基本语法 可重载的运算符列表 基本原则 编程示例 代码解…...

答疑解惑:EMC VMAX3 MMCS控制台不定期重启原因分析

今天有个朋友咨询他们有一台EMC的VMAX100k设备&#xff0c;其中MMCS2的管理控制台定期重启&#xff0c;但始终无法找到重启原因&#xff0c;稍微花了点时间&#xff0c;帮客户看了下。先说结论&#xff0c;MMCS2确实不定期发生重启&#xff0c;每次reboot都是一样的message信息…...

单例模式(Singleton Pattern)

单例模式&#xff08;Singleton Pattern&#xff09; 任务管理器可以作为一个全局的任务配置管理类&#xff0c;使用单例模式保证全局只有一个实例。这样你可以避免在应用程序中创建多个任务管理对象&#xff0c;保持配置参数的统一。 示例&#xff1a; class TaskManager { …...

树莓派超全系列文档--(8)RaspberryOS实用程序

RaspberryOS实用程序 实用程序kmsprintvclogvcgencmdvcosversionget_throttledmeasure_tempmeasure_clock [clock]measure_volts [block]otp_dumpget_config [configuration item|int|str]get_mem typecodec_enabled [type]mem_oommem_reloc_statsread_ring_osc 文章来源&#…...

Rust 与 FFmpeg 实现视频水印添加:技术解析与应用实践

引言 在短视频、直播、影视制作等领域&#xff0c;视频水印是一种常见的工具&#xff0c;用于保护版权、提升品牌辨识度或满足合规性要求。然而&#xff0c;开发者在实现水印添加时往往面临以下挑战&#xff1a; 手动处理效率低&#xff1a;使用图像编辑软件&#xff08;如 P…...

绿联NAS安装内网穿透实现无公网IP也能用手机平板远程访问经验分享

文章目录 前言1. 开启ssh服务2. ssh连接3. 安装cpolar内网穿透4. 配置绿联NAS公网地址 前言 大家好&#xff0c;今天给大家带来一个超级炫酷的技能——如何在绿联NAS上快速安装cpolar内网穿透工具。想象一下&#xff0c;即使没有公网IP&#xff0c;你也能随时随地远程访问自己…...

如何在 React 项目中使用React.lazy和Suspense实现组件的懒加载?

大白话如何在 React 项目中使用React.lazy和Suspense实现组件的懒加载&#xff1f; 在 React 项目里&#xff0c;有时候组件功能多、体积大&#xff0c;要是一次性把所有组件都加载进来&#xff0c;网页加载速度就会变慢。而 React 提供了 React.lazy 和 Suspense 这两个好东西…...

虫洞数观系列一 | 豆瓣电影TOP250数据采集与MySQL存储实战

目录 系列文章 1. 引言 2 技术栈Request 2.1请求头headers 2.2查找定位信息 2.3处理网页html结构化数据 2.4每页url规律 2.5逐条查找所需信息 2.6完整代码 3 数据存储至mysql 3.1新建数据库 3.2编写数据库写入py文件 3.2.1构建1个执行sql语句的函数 3.2.2构造一个…...

模型 阿米巴模式

系列文章分享模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。小团队独立经营&#xff0c;企业活力无限。 1 阿米巴模式的应用 1.1 日航重生&#xff08;航空业成功案例&#xff09; 应用领域 航空运输业破产重组与组织激活 案例名称 日本航空&#xff08;JAL&…...

针对stm32F103C8t6芯片调节USB串口的经验

1、首先这是自己手搓的板子,对于之前一直没有了解过USB这方面,则这个针对USB部分没有设计上拉电阻,造成不管怎么调节PC端都没有反应。 图一 这个没有添加1.5K电阻 这个D+位置应该再接一个1.5KR的电阻如图2所示 图2 这样调节的话PC端就可以识别到USB串口,但是这是串口还是会…...

JVM详解(包括JVM内存模型与GC垃圾回收)

&#x1f4d6;前言&#xff1a; 学会使用Java对于一个程序员是远远不够的。Java语法的掌握只是一部分&#xff0c;另一部分就是需要掌握Java内部的工作原理&#xff0c;从编译到运行&#xff0c;到底是谁在帮我们完成工作的&#xff1f; 接下来着重对Java虚拟机&#xff0c;也就…...

解锁DeepSeek潜能:Docker+Ollama打造本地大模型部署新范式

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《深度探秘&#xff1a;AI界的007》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、什么是Docker 2、什么是Ollama 二、准备工作 1、操…...

【Linux网络】——Socket网络编程

前言 在当今数字化的时代&#xff0c;网络通信已经成为计算机领域不可或缺的一部分。无论是日常的网页浏览、社交媒体交互&#xff0c;还是大规模的企业级数据传输&#xff0c;都离不开高效可靠的网络通信。而在Linux操作系统中&#xff0c;Socket网络编程是实现各种网络应用的…...

基于javaweb的SpringBoot雪具商城系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...

Android 简化图片加载与显示——使用Coil和Kotlin封装高效工具类

为了简化使用Coil加载网络图片和GIF的过程&#xff0c;我们可以封装一个工具类。这个工具类将包括初始化ImageLoader的方法、加载图片到ImageView的方法&#xff0c;以及可能的其他便捷方法&#xff0c;如加载圆形图片、设置占位图等。下面是一个示例&#xff1a; 首先&#x…...

Flink watermark的时间字段有空值,建表的时候,如何处理

在 Flink 中处理时间字段存在空值时&#xff0c;需通过 表定义阶段的特殊处理 和 Watermark 生成策略调整 来避免因空值导致的窗口计算异常或任务失败。以下是具体解决方案及实现方法&#xff1a; 1. 空值处理核心策略 1.1 查询时&#xff0c;过滤空值数据&#xff08;推荐&am…...

关于matlab和python谁快的问题

关于matlab和python谁快的问题&#xff0c;python比matlab在乘法上快10倍&#xff0c;指数计算快4倍&#xff0c;加减运算持平&#xff0c;略慢于matlab。或许matlab只适合求解特征值。 import torch import timen 50000 # 矩阵规模 M torch.rand(n, 31)start_time time.t…...

【DevOps】DevOps and CI/CD Pipelines

DevOps 是一种将开发与运维实践相结合的模式&#xff0c;旨在缩短软件开发周期并交付高质量软件。 DevOps 是什么&#xff1f; 开发团队与运维团队之间的协作 • 持续集成与持续交付&#xff08;CI/CD&#xff09; • 流程自动化 • 基础设施即代码&#xff08;IaC&#xff09;…...

ROS--IMU数据包

IMU惯性测量单元 一&#xff1a;IMU二&#xff1a;ROS中三&#xff1a;IMU数据包三&#xff1a;总结 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一&#xff1a;IMU IMU&#xff08;Inertial Measurement Unit&#xff0c;惯性测量单元&#xff09…...

【机器学习】手撕封装PCA——将高维数据映射到低维数据的过程

PCA将高维数据映射到低维数据的过程 一、摘要二、PCA的降维思路三、PCA代码实现降维过程3.1 PCA类的实现与封装3.2 PCA类的使用示例 四、PCA的恢复过程 一、摘要 本文详细介绍了主成分分析法&#xff08;PCA&#xff09;在高维数据降维中的应用。首先&#xff0c;阐述了PCA的基…...

LangChain开发(七)自定义输出格式(JSON/XML/YAML)

文章目录 JSON结构输出未使用PydanticPydantic流式处理 XML结构输出xml输出指定字段 YAML输出源码地址参考资料 JSON结构输出 虽然一些模型提供商支持内置的方法返回结构化输出&#xff0c;但并非所有都支持。我们可以使用输出解析器来帮助用户通过指示指定任意的JSON模型&…...

RustDesk部署到linux(自建服务器)

简介 ‌RustDesk‌是一款开源的远程桌面软件&#xff0c;由中国开发者开发&#xff0c;使用Rust编程语言构建。它支持跨平台运行&#xff0c;可以在Windows、macOS、Linux、iOS、Android和Web等多个平台上使用。RustDesk的主要功能包括远程桌面访问、文件传输、文本聊天等&…...

分布式锁,redisson,redis

目录 什么是分布式锁分布式锁解决什么问题分布式锁的特点使用分布式锁的场景怎么使用分布式锁1. 添加依赖2. 配置 Redisson 客户端3. 使用 Redisson 实现分布式锁 什么是分布式锁 分布式锁是一种锁机制&#xff0c;用于在分布式环境下&#xff0c;解决多个线程并发访问同一共享…...

linux常用指令(9)

加油同志们,我们离胜利不远了,再有两天我们就可以了解完linux的一些基本常用指令了,到时我们便可以进入一些shell脚本语法了,那么话不多说,来看. 1.more指令 功能描述&#xff1a;more指令是一个基于vi编辑器的文本过滤器,它以全屏幕的方式按页显示文本文件的内容. 基本语法…...

深入解析 JVM 内存区域及核心概念

深入解析 JVM 内存区域及核心概念 Java 虚拟机&#xff08;JVM&#xff09;内部划分了多个内存区域&#xff0c;每个区域存储不同类型的数据并承担不同的职责。本文将详细介绍以下内容&#xff1a; 程序计数器&#xff1a;记录当前线程正在执行的字节码指令及其“行号”信息&a…...

字节跳动春招研发部笔试题解

字节跳动春招研发部笔试题 1.万万没想到之聪明的编辑 我叫王大锤&#xff0c;是一家出版社的编辑。我负责校对投稿来的英文稿件&#xff0c;这份工作非常烦人&#xff0c;因为每天都要去修正无数的拼写错误。但是&#xff0c;优秀的人总能在平凡的工作中发现真理。我发现一个发…...

java对象模型

java对象自身的存储模型JVM会给这个类创建一个instanceKlass&#xff0c;保存在方法区&#xff0c;用来在JVM层表示该Java类。 a类。当我们在Java代码中&#xff0c;使用new创建一个对象的时候&#xff0c;JVM会在栈中给对象赋值&#xff0c;会在堆中创建一个instanceOopDesc对…...

深入理解指针(3)(C语言版)

文章目录 前言 一、字符指针变量二、数组指针变量2.1 数组指针变量是什么2.2 数组指针变量怎么初始化2.2.1 静态初始化2.2.2 动态初始化 三、二维数组传参的本质四、函数指针变量4.1 函数指针变量的创建4.2 函数指针变量的使用4.3 typedef关键字4.4拓展 五、函数指针数组六、转…...

Linux内核 内存管理 物理内存初始化流程

1.‌ARM64页表初始化流程图 start_kernel()│▼ setup_arch() // 架构相关初始化│▼ early_fixmap_init() // 初始化Fixmap&#xff08;临时映射设备树等&#xff09;│▼ arm64_memblock_init() // 从设备树解析内存布局│▼ arm…...

Day23:和为s的数字

购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况&#xff0c;返回任一结果即可。 示例 1&#xff1a; 输入&#xff1a;price [3, 9, 12, 15], target 18 输出&#xff1a;[3,15] 或者 [15,3]示例 2&#x…...

Transformer 通关秘籍2:利用 BERT 将文本 token 化

前面两节分别通过两个代码示例展示了模型将文本转换为 token 之后是什么样的&#xff0c;希望你可以对此有一个感性的认识。 本节来简要介绍一下将一个连续的文本转换为 token 序列的大致过程&#xff0c;这个过程被称为分词&#xff0c;也叫 tokenization。 在你没了解这方面…...

电脑干货:万能驱动--EasyDrv8

目录 万能驱动EasyDrv8 功能介绍 主程序界面 驱动解压与安装 PE环境支持 系统部署环境 桌面环境一键解决方案 万能驱动8电脑版是由IT天空出品的一款智能识别电脑硬件并自动安装驱动的工具&#xff0c;一般又称为it天空万能驱动&#xff0c;万能驱动vip版&#xff0c;简称…...

18502 字符串哈希匹配字符串

18502 字符串哈希匹配字符串 ⭐️难度&#xff1a;中等 &#x1f31f;考点&#xff1a;字符串hash &#x1f4d6; &#x1f4da; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner;public class Main {static int…...

openmmlab介绍 一下

OpenMMLab 是由商汤科技&#xff08;SenseTime&#xff09;发起并维护的开源深度学习项目&#xff0c;专注于计算机视觉领域。它提供了一系列模块化、可扩展的工具库&#xff0c;旨在帮助研究者和开发者高效地实现、复现和部署前沿的视觉算法。OpenMMLab 的设计强调‌模块化‌、…...

基于javaweb的SpringBoot线上网络文件管理系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...

【设计模式】工厂模式详解-----简单工厂模式、工厂方法模式、抽象工厂模式

工厂模式详解 一、概述 工厂模式&#xff08;Factory Pattern&#xff09; 是一种 创建型设计模式&#xff0c;用于 封装对象的创建逻辑&#xff0c;避免在代码中直接实例化对象&#xff0c;从而提高代码的 可维护性、扩展性和解耦性。 二、工厂模式分类 工厂模式包括 简单工…...

【雅思播客09】Turn Left here.

Hello everyone! And welcome to my channel! Im Reevs. Good morning! 大家好&#xff0c;欢迎来到懒人英语晨读栏目&#xff0c;我是Reevs&#xff0c;早上好呀。 I have a great lesson for you today. 今天我有一堂非常棒的课。 We have an elementary lesson, which is …...

初阶7 vector

本章重点 vector的介绍vector的使用vector的模拟实现 1.vector的介绍 vector就类似数据结构中的顺序表 vector是表示可变大小数组的序列容器。 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。 意味着可以采用下标对vector的元素 进行访问&#xff0c;和数…...

归并排序总结

归并排序是分治法的典型应用&#xff0c;把两个或k个有序的子序列合并为一个。2路归并&#xff0c;2合一。k路归并&#xff0c;k合一。内部排序通常采用2路归并排序&#xff0c;先将数组分成两半&#xff0c;分别排序&#xff0c;然后合并。合并的过程需要将两个有序的子数组合…...

ollama迁移已下载的单个模型到服务器

ollama迁移已下载的单个模型到服务器 场景 ollama是面向用户级的&#xff0c;部署和运行都很简单&#xff0c;是否高效就另说了。但最起码&#xff0c;他能充分利用用户的硬件设备&#xff0c;在GPU不足也能调用cpu和内存去加持。 ollama运行的模型基本是量化版本的&#xf…...

基于SSM+Vue物流信息管理系统(附源码)

预览页面 获取方式 https://gitee.com/XiaoLin_Java/communion/blob/master/README.en.md...

docker创建registry镜像仓库2.8版本

目录 shell脚本内容 运行效果 问题与解决 涉及镜像包registry:2.8&#xff08;x86版本&#xff09; shell脚本内容 [roottest1 docker]# cat registry.sh #!/bin/bash read -p "请输入用户:" user read -p "请输入密码:" passpathpwd passdir"$…...