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

Linux:多线程[2] 线程控制

了解:
Linux底层提供创建轻量级进程/进程的接口clone,通过选择是否共享资源创建。
vforkfork都调用的clone进行实现,vfork和父进程共享地址空间-轻量级进程。
库函数pthread_create调用的也是底层的clone

POSIX线程库
与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”打头的
要使用这些函数库,要通过引入头文件<pthread.h>
链接这些线程函数库时要使用编译器命令的“-lpthread”选项。

功能:创建一个新的线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *
(*start_routine)(void*), void *arg);
参数
thread:返回线程ID
attr:设置线程的属性,attr为NULL表示使用默认属性
start_routine:是个函数地址,线程启动后要执行的函数
arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码;并不设置error错误码,因为错误码会针对整个进程

1.线程创建 pthread_create

class ThreadDate//定义一个类传给每个创建的新线程来命名区分它们
{
public:pthread_t tid;char namebuffer[64];int number;
};
void* thread_routine(void *args)//新线程调用的函数
{ThreadDate *td = static_cast<ThreadDate *>(args);//安全的进行强制类型转化int cnt = 10;while(cnt){cout<<" new thread create success,name: "<<td->namebuffer<<" cnt:"<<cnt--<<endl;sleep(1);}return nullptr;
}
int main()
{vector<ThreadDate*> threads;
#define NUM 10for(int i=0;i<NUM;i++)//主线程创建十个新线程{ ThreadDate *td = new ThreadDate();//char namebuffer[64];td->number = i+1;snprintf(td->namebuffer,sizeof(td->namebuffer),"%s:%d","thread",i+1);pthread_create(&td->tid,nullptr,thread_routine,td);//td是自定义类型,传参时会拷贝,threads.push_back(td);//创建成功时将每一个新线程信息保留}return 0;
}

传给新线程的变量定义在堆栈上的区别: 当我们要创建多个线程时,我们需要传参数void *arg来对每个线程进行命名来区分它们。如果我们定义char namebuffer[64];因为新线程与主线程的异步性;如果定义到了循环里,每次循环结束这个局部变量就已经被销毁了,但被创建出来的进程还保留着指向它的地址,那么这个地址中存的东西可能会被别的变量覆盖;如果是new一个自定义类的空间,是因为在堆上所以生命周期长不会被覆盖。

2.线程终止 pthread_exit / return


——退出信号:
为什么没有见到,线程退出的时候,对应的退出信号?? 线程出异常,收到信号,整个进程会退出!thread_join:默认就认为函数会调用成功!不考虑异常的问题,异常是进程要考虑的问题。
如果一个线程出了异常,会影响其它进程吗?-所有线程退出(健壮性或鲁棒性过差)。
一个线程出现野指针问题向所有PID为该值的线程都写入11号信号段错误;一个线程出错这个进程就发生异常,OS会回收该进程的资源,剩余的线程也不会活下去。
进程不会相互影响,因为进程有独立的资源。用exit()退出线程则会终止该线程所在的整个进程。

——返回值
pthread_exit(nullptr);
return nullptr; 线程的函数跑完了也就相当于该线程跑完了,用return也可以结束。
返回值的参数类型是void *retval,join传入void**类型指针即可拿到该返回值。此处也可以用自定义类的方式作为返回值,返回线程终止时的各种状态。

class ThreadReturn
{
public:int exit_code;int exit_result;
};
void* thread_routine(void *args)//可重入状态--是可重入函数
{//... ...ThreadReturn *tr = new ThreadReturn();//ThreadReturn tr;//在栈上定义,牵扯到会被释放的问题return (void*)&tr;tr->exit_code = 1;tr->exit_result = 106;return (void*)tr;//右值//pthread_exit((void*)tr);
}
int main()
{//... ...for(auto &iter : threads){ThreadReturn *ret = nullptr;int n = pthread_join(iter->tid,(void**)&ret);//void ** retp;*retp,从库中获取指定线程的输出结果assert(n==0);cout<<"jion :"<<iter->namebuffer<<"success,exit_code: "<<ret->exit_code<<",exit_result: "<<ret->exit_result<<endl;delete iter;} cout<<"main thread quit"<<endl;return 0;
}

3.线程等待回收 pthread_join

线程退出时它的PCB也需要释放,如果不等待,会造成类似僵尸进程的问题(暂时无法查看),造成内存泄漏。<1.所以我们要获取新线程的退出信息,<2.回收新线程的内存资源,避免内存泄漏。

 vector<ThreadDate*> threads;
#define NUM 10
for(int i=0;i<NUM;i++)//主线程创建十个新线程{ ThreadDate *td = new ThreadDate();td->number = i+1;snprintf(td->namebuffer,sizeof(td->namebuffer),"%s:%d","thread",i+1);pthread_create(&td->tid,nullptr,thread_routine,td);//td是自定义类型,传参时会拷贝,threads.push_back(td);//创建成功时将每一个新线程信息保留}
for(auto &iter : threads)//主线程打印出它所创建的所有新线程{cout<<"create thread:"<<iter->namebuffer<<":"<<iter->tid<<"  suceess"<<endl;}
for(auto &iter : threads)//主线程回收创建出来的所有新线程{int n = pthread_join(iter->tid,nullptr);assert(n==0);cout<<"jion :"<<iter->namebuffer<<"success"<<endl;delete iter;}

线程返回值
为什么return和pthread_exit(nullpter)参数都是nullptr 
void **retval用来获取线程函数结束时,返回的退出结果!

4.线程取消pthread_cancel

//线程是可以被cancel取消的!注意:线程要被取消,前提是这个线程已经被运行起来了。for(int i=0;i<threads.size()/2;i++)//主线程打印出它所创建的所有新线程{pthread_cancel(threads[i]->tid);//PTHREAD_CANCELED -1cout<<"pthread_cancel :"<<threads[i]->namebuffer<<"success"<<endl;}for(auto &iter : threads){void *ret = nullptr;//我们在thread_routine返回一个return (void*)100;int n = pthread_join(iter->tid,(void**)&ret);//void ** retp;*retp,从库中获取指定线程的输出结果assert(n==0);cout<<dec<<"jion :"<<iter->namebuffer<<"success,exit_code: "<<(long long)ret<<endl;delete iter;} cout<<"main thread quit"<<endl;

实验结果显示:cancel取消的进程返回jion回收的结果返回的都是-1(宏PTHREAD_CANCELED);没被取消的进程被jion回收的值都是我们在thread_routine中设定的返回值return (void*)100;

5.补充:初步重新认识线程库(语言版)

任何语言在Linux中要实现多线程,必定要使用Pthread库,如何看待c++11中的多线程?c++11的多线程,在Linux环境中,本质是对pthread库的封装!
推荐使用C++,如果在纯Linux环境下推荐使用原生线程库。在Windows环境中,语言对库的封装解决了平台的差异性,可以跨平台。在主流的框架中直接使用的原生线程库。

#include<iostream>
#include<thread>
#include<unistd.h>
void thread_run()
{while(true){std::cout<<"我是新进程..."<<std::endl;sleep(1);}
}
int main()
{std::thread t1(thread_run);while(true){std::cout<<"我是主线程..."<<std::endl;sleep(1);}t1.join();return 0;
}

6.线程分离

线程是可以等待的,等待的时候使用jion—阻塞式,如果不等待就会造成PCB内存泄漏,类似于僵尸进程的问题。线程不存在非阻塞式等待,那如果不等待呢?
—默认情况下,新创建的线程是joinable的(jionable表示该线程必须被jion),线程退出后,需要对其进行pthread_join操作,否则无法释放资源,从而造成系统泄漏。
—如果不关心线程的返回值,join是一种负担,这个时候,我们可以告诉系统,当线程退出时,自动释放线程资源。这种情况就被成为线程分离。

6.1pthread_self()接口,获取自己的线程ID
std::string changeId(const pthread_t &thread_id)//格式化一下传入的线程ID
{char tid[128];snprintf(tid,sizeof(tid),"0x%x",thread_id);return tid;
}
void *start_routine(void *args)
{pthread_detach();//1.join时还没分离std::string threadname = static_cast<const char*>(args);while(true){std::cout<<threadname<<"running...:"<<changeId(pthread_self())<<std::endl;sleep(1);}
}
int main()
{pthread_t tid;pthread_create(&tid,nullptr,start_routine,(void*)"thread 1");pthread_detach(tid);//2.确保在join之前分离std::string main_id = changeId(pthread_self());std::cout<<"main thread running...\n"<<"主线程ID:"<<main_id<<"新线程ID:"<<changeId(tid)<<std::endl;pthread_join(tid,nullptr);//回收tid的线程,不关心返回值传nullptr
}

6.2 pthread_detach分离一个线程(参数是线程ID)

主线程join的时候,新线程还没执行分离...;所以得在主函数的join之前,新线程创建之后进行分离。

7.补充:创建一个线程对应库和内核所做的工作:

操作系统对系统内的多进程,库要对线程做管理——先描述(线程的属性:tid/独立栈/...),再组织。在库中要创建线程的结构体,在库中用户级线程,用户关心的线程属性在库中,内核提供线程执行流的调度,Linux中用户级线程:内核轻量级进程=1:1。
用户级线程ID究竟是什么?
堆栈之间有一个共享区,库是一个磁盘文件(库文件),进程要访问一个库必须将它加载到内存映射到地址空间当中,通过地址空间和页表找到库对应的共享区,在库中每一个线程当被创建时,在内核中给它创建对应的线程ID,在库当中也要给它创建一个描述线程的结构体(TCB:)。所有线程的TCB都放在一个数组中,线程ID就是该线程在库中TCB的地址。 所以当一个线程终止时,它的返回值就通过它在库中的地址也就是线程ID放入TCB中,join时即可拿到。而每个线程的私有栈都在它们库中的TCB中,多个轻量级进程每个所对应的栈,主线程的栈是在地址空间中,其它线程的栈在线程库中。  底层创建轻量级进程是库调用clone创建的。
主线程调用库创建新线程,库先为新线程创建一个TCB,然后调用Linux提供创建轻量级进程的接口clone,将创建好的TCB对应的回调方法、私有栈、参数传递给clone,所以线程一旦创建好了就会依赖我们的原生线程库。

线程的局部存储
想给线程定义一些私有的属性,不想放在栈上或者malloc在堆上,就想这个线程在运行起来后就天然具有独立的空间,你就可以设置私有属性,这种局部存储就是介于全局变量和局部变量之间的线程特有的一种属性。

__thread int thread_specific_variable;

8.自定义实现原生线程的封装

.hpp里面既包括方法的声明也包括方法的定义,在使用时只要包括它即可。

#pragma once
#include <iostream>
#include <string>
#include <pthread.h>
#include <cstring>
#include <functional>
#include <cassert>
class thread;
class context//上下文,当成一个大号的结构体——解决this指针的问题
{
public:Thread *this_;void *args_;
public:context():this_(nullptr),args_(nullptr);{}~context(){}
};class thread
{
public://using func_t = std::function<void*(void*)>;typedef std::function<void*(void*)> func_t;//C++的函数对象const int num = 1024;
public:Thread(func_t func,void *args,int number)//构造函数,初始化func和用number线程name:func_(func),args_(args){char buffer[num];//c99支持//name_ = "thread_";//name_+=std::to_string(number);snprintf(buffer,sizeof buffer,"thread-%d",number);name_ = buffer;}//在类内创建线程,想让线程执行对应的方法,需要将方法设置成为staticstatic void *start_routine(void *args)//类内成员,隐含this会和pthread_create参数不一致会有两个参数导致不一致{context *ctx = static_cast<context *>(args);void *ret = ctx->this_->run(ctx->args_);delete ctx;return ret;//静态方法不能调用成员方法和成员变量,只能调用静态成员方法和变量//return func_(args_);//复习类中的static修饰!!!!}void start(){context *ctx = new context();ctx->this_ = this;ctx->args_ = args_;int n = pthread_create(&tid_,nullptr,start_routine,ctx);//函数是C++规则,调用c式接口assert(n == 0);//编译debug的方式发布的时候存在,release方式发布,assert就不存在了,n就只被定义没使用(void)n;//意料之外用if/异常,意料之中用assert}void join(){int n = pthread_join(tid_,nullptr);assert(n==0);(void)n;}void *run(void *args){func_(args);}~Thread(){//do nothing}
private:std::string name_;func_t func_;//线程未来要运行时所要执行的函数pthread_t tid_;void *args_;//未来执行时带的参数
};

相关文章:

Linux:多线程[2] 线程控制

了解&#xff1a; Linux底层提供创建轻量级进程/进程的接口clone&#xff0c;通过选择是否共享资源创建。 vfork和fork都调用的clone进行实现&#xff0c;vfork和父进程共享地址空间-轻量级进程。 库函数pthread_create调用的也是底层的clone。 POSIX线程库 与线程有关的函数构…...

010 mybatis-PageHelper分页插件

文章目录 添加依赖配置PageHelper项目中使用PageHelper注意事项 PageHelper分页插件介绍 https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/en/HowToUse.md 使用方法 添加依赖 <dependency><groupId>com.github.pagehelper</groupId>&l…...

【huawei】云计算的备份和容灾

目录 1 备份和容灾 2 灾备的作用&#xff1f; ① 备份的作用 ② 容灾的作用 3 灾备的衡量指标 ① 数据恢复时间点&#xff08;RPO&#xff0c;Recoyery Point Objective&#xff09; ② 应用恢复时间&#xff08;RTO&#xff0c;Recoyery Time Objective&#xff09; 4…...

CVE-2023-38831 漏洞复现:win10 压缩包挂马攻击剖析

目录 前言 漏洞介绍 漏洞原理 产生条件 影响范围 防御措施 复现步骤 环境准备 具体操作 前言 在网络安全这片没有硝烟的战场上&#xff0c;新型漏洞如同隐匿的暗箭&#xff0c;时刻威胁着我们的数字生活。其中&#xff0c;CVE - 2023 - 38831 这个关联 Win10 压缩包挂…...

回顾:Maven的环境搭建

1、下载apache-maven-3.6.0 **网址:**http://maven.apache.org 然后解压到指定的文件夹&#xff08;记住文件路径&#xff09; 2、配置Maven环境 复制bin文件夹 的路径D:\JavaTool\apache-maven-3.6.0\bin 环境配置成功 3、检查是否配置成功 winR 输入cmd 命令行输入mvn -v…...

从零到全栈开发

HTML&#xff1a;超文本标记语言 CSS&#xff1a;层叠样式表 HTML可以理解为框架----&#xff08;毛坯房&#xff09; CSS 可以理解为装修----&#xff08;装修&#xff09; 学习工具&#xff1a; Vscode应用----扩展&#xff08;中文&#xff09; AI ----KiMi &#xff0c;豆…...

单片机-STM32 WIFI模块--ESP8266 (十二)

1.WIFI模块--ESP8266 名字由来&#xff1a; Wi-Fi这个术语被人们普遍误以为是指无线保真&#xff08;Wireless Fidelity&#xff09;&#xff0c;并且即便是Wi-Fi联盟本身也经常在新闻稿和文件中使用“Wireless Fidelity”这个词&#xff0c;Wi-Fi还出现在ITAA的一个论文中。…...

两种交换排序算法--冒泡,快速

目录 1.冒泡排序原理 2.快速排序原理 3.冒泡代码实现 4.快速排序代码实现 1.冒泡排序原理 冒泡排序&#xff08;Bubble Sort&#xff09;是一种简单的排序算法&#xff0c;基本思想是通过反复交换相邻的元素&#xff0c;直到整个序列有序。它的名字来源于较大的元素像气泡…...

langchain基础(一)

模型又可分为语言模型&#xff08;擅长文本补全&#xff0c;输入和输出都是字符串&#xff09;和聊天模型&#xff08;擅长对话&#xff0c;输入时消息列表&#xff0c;输出是一个消息&#xff09;两大类。 以调用openai的聊天模型为例&#xff0c;先安装langchain_openai库 1…...

【学术会议征稿】第五届能源、电力与先进热力系统学术会议(EPATS 2025)

能源、电力与先进热力系统设计是指结合物理理论、工程技术和计算机模拟&#xff0c;对能源转换、利用和传输过程进行设计的学科领域。它涵盖了从能源的生产到最终的利用整个流程&#xff0c;旨在提高能源利用效率&#xff0c;减少能源消耗和环境污染。 重要信息 官网&#xf…...

MyBatis框架基础学习及入门案例(2)

目录 一、数据库建表(tb_user)以及添加数据。 &#xff08;1&#xff09;数据库与数据表说明。 &#xff08;2&#xff09;字段与数据说明。 二、创建模块(或工程)、导入对应所需依赖坐标。 三、编写MyBatis核心主配置文件。(解决JDBC中"硬编码"问题) &#xff08;1&…...

Salesforce Too Many Email Invocations: 11

在 Salesforce 中&#xff0c;“Too Many Email Invocations: 11” 错误通常表示您的组织在单个事务中超过了 Apex 电子邮件调用的限制。Salesforce 设置这些限制是为了防止滥用并确保公平使用。以下是解决该问题的方法&#xff1a; 理解限制 Salesforce 允许每个事务中最多进…...

2274. 不含特殊楼层的最大连续楼层数

2274. 不含特殊楼层的最大连续楼层数 题目链接&#xff1a;2274. 不含特殊楼层的最大连续楼层数 代码如下&#xff1a; class Solution { public:int maxConsecutive(int bottom, int top, vector<int>& special) {ranges::sort(special);int res max(special[0] …...

RGB 转HSV空间颜色寻找色块

文章目录 前言一、绿色确定二、红色确定总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 项目需要&#xff1a; 将RGB颜色空间转换为HSV颜色空间以寻找颜色&#xff0c;主要基于以下几个原因&#xff1a; 直观性&#xff1a; HSV颜色空间更符合人类…...

Kafka生产者ACK参数与同步复制

目录 生产者的ACK参数 ack等于0 ack等于1&#xff08;默认&#xff09; ack等于-1或all Kafka的同步复制 使用误区 生产者的ACK参数 Kafka的ack机制可以保证生产者发送的消息被broker接收成功。 Kafka producer有三种ack机制 &#xff0c;分别是 0&#xff0c;1&#xf…...

计算机图形学试题整理(期末复习/闭or开卷/>100道试题/知识点)

1.各种坐标变换&#xff0c;会产生变换前后维度改变的是&#xff08;投影变换&#xff09;。 A&#xff09;建模变换&#xff1b;B&#xff09;观察变换&#xff1b;C&#xff09;投影变换&#xff1b;D&#xff09;视口变换 不同的坐标变换对维度的影响如下&#xff1a; 建模…...

Ubuntu 24.04 安装 NVIDIA Container Toolkit 全指南:让Docker拥抱GPU

Ubuntu 24.04 安装 NVIDIA Container Toolkit 全指南&#xff1a;让Docker拥抱GPU 前言一、环境准备1.1 验证驱动状态 二、安装NVIDIA Container Toolkit2.1 添加官方仓库2.2 执行安装 三、配置Docker运行时3.1 更新Docker配置 四、验证安装结果4.1 运行测试容器 五、实战应用 …...

python3+TensorFlow 2.x(三)手写数字识别

目录 代码实现 模型解析&#xff1a; 1、加载 MNIST 数据集&#xff1a; 2、数据预处理&#xff1a; 3、构建神经网络模型&#xff1a; 4、编译模型&#xff1a; 5、训练模型&#xff1a; 6、评估模型&#xff1a; 7、预测和可视化结果&#xff1a; 输出结果&#xff…...

aws(学习笔记第二十六课) 使用AWS Elastic Beanstalk

aws(学习笔记第二十六课) 使用aws Elastic Beanstalk 学习内容&#xff1a; AWS Elastic Beanstalk整体架构AWS Elastic Beanstalk的hands onAWS Elastic Beanstalk部署node.js程序包练习使用AWS Elastic Beanstalk的ebcli 1. AWS Elastic Beanstalk整体架构 官方的guide AWS…...

GestureDetector组件的功能与用法

文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了ListView响应事件的内容,本章回中将介绍GestureDetector Widget.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 概念介绍 我们在这里介绍的GestureDetector是一个事件响应Widget,它可以响应双击事件&…...

【HuggingFace项目】:Open-R1 - DeepSeek-R1 大模型开源复现计划

项目链接&#xff1a;https://github.com/huggingface/open-r1 概述 Open-R1 是由 HuggingFace 发布的一个完全开放的项目&#xff0c;旨在通过三个主要步骤复现 DeepSeek-R1 的完整训练流程。这个项目的目标是让更多人能够理解和使用 DeepSeek-R1 的技术方案&#xff0c;从而…...

K8S中数据存储之配置存储

配置存储 在Kubernetes中&#xff0c;ConfigMap和Secret是两种核心资源&#xff0c;用于存储和管理应用程序的配置数据和敏感信息。理解它们的功能和最佳实践对于提高Kubernetes应用程序的安全性和配置管理的效率至关重要。 ConfigMap ConfigMap是一种API对象&#xff0c;允许…...

群辉折腾日记【连续剧】

安装群辉6.23版本 对比不同的版本以及自己的硬件条件&#xff0c;我选择了6.2.3稳定养老版本&#xff0c;硬件参数可以看之前的文章&#xff1a;pve (群辉、软路由、win/linux)折腾日记 之前年轻气盛喜欢折腾&#xff0c;秉持着一个原则&#xff0c;可以不用&#xff0c;但不能…...

AIGC视频生成模型:慕尼黑大学、NVIDIA等的Video LDMs模型

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍慕尼黑大学携手 NVIDIA 等共同推出视频生成模型 Video LDMs。NVIDIA 在 AI 领域的卓越成就家喻户晓&#xff0c;而慕尼黑大学同样不容小觑&#xff0c;…...

Hadoop 与 Spark:大数据处理的比较

&#x1f496; 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长…...

VB6.0 显示越南语字符

近期接到客户咨询&#xff0c;说是VB6.0写软件界面上显示越南语乱码&#xff0c;需要看看怎样解决。 我在自己电脑上也试了下&#xff0c;确实显示越南语结果是乱码。编辑器里乱码&#xff0c;运行起来界面上也是乱码。 经过一天的折腾&#xff0c;算是解决了问题&#xff0c…...

微信小程序中实现进入页面时数字跳动效果(自定义animate-numbers组件)

微信小程序中实现进入页面时数字跳动效果 1. 组件定义,新建animate-numbers组件1.1 index.js1.2 wxml1.3 wxss 2. 使用组件 1. 组件定义,新建animate-numbers组件 1.1 index.js // components/animate-numbers/index.js Component({properties: {number: {type: Number,value…...

网络仿真工具Core环境搭建

目录 安装依赖包 源码下载 Core安装 FAQ 下载源码TLS出错误 问题 解决方案 找不到dbus-launch 问题 解决方案 安装依赖包 调用以下命令安装依赖包 apt-get install -y ca-certificates git sudo wget tzdata libpcap-dev libpcre3-dev \ libprotobuf-dev libxml2-de…...

JavaScript 的 Promise 对象和 Promise.all 方法的使用

JavaScript 中的 Promise 对象 什么是 Promise? Promise 是一种用于处理异步操作的对象。它代表一个尚未完成但预计将来会完成的操作及其结果。 主要特点&#xff1a; 状态: Pending&#xff08;进行中&#xff09;: 初始状态&#xff0c;既未成功&#xff0c;也未失败。Fu…...

农产品价格报告爬虫使用说明

农产品价格报告爬虫使用说明 # ************************************************************************** # * * # * 农产品价格报告爬虫 …...

Java 大视界 -- Java 大数据中的隐私增强技术全景解析(64)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

实战Linux Swap扩展分区

文章目录 定义命令格式案例注释 定义 Swap分区是Linux系统中的一种虚拟内存实现方式&#xff0c;它是磁盘上预留的专用区域。当系统的物理内存不足时&#xff0c;会将部分不活跃的数据从物理内存移动到Swap分区&#xff0c;从而释放更多可用内存空间。 命令格式 关闭Swap分区…...

doris:Parquet导入数据

本文介绍如何在 Doris 中导入 Parquet 格式的数据文件。 支持的导入方式​ 以下导入方式支持 Parquet 格式的数据导入&#xff1a; Stream LoadBroker LoadINSERT INTO FROM S3 TVFINSERT INTO FROM HDFS TVF 使用示例​ 本节展示了不同导入方式下的 Parquet 格式使用方法…...

Synology 群辉NAS安装(6)安装mssql

Synology 群辉NAS安装&#xff08;6&#xff09;安装mssql 写在前面mssql 2019:成功安装说明&#xff0c;这个最终成功了 mssql 2022没有成功1. pull image2.启动mssql docker container 远程连接 写在前面 mssq是一个重要节点。 这是因为我对mysql没有一丝好感。虽然接触了许…...

使用.NET 8构建高效的时间日期帮助类

使用.NET 8构建高效的时间日期帮助类 在现代Web应用程序中&#xff0c;处理日期和时间是一个常见的需求。无论是记录日志、生成报告还是进行数据分析&#xff0c;正确处理日期和时间对于确保数据的准确性和一致性至关重要。本文将详细介绍如何使用ASP.NET Core和C#构建一个高效…...

第26篇 基于ARM A9处理器用C语言实现中断<二>

Q&#xff1a;基于ARM A9处理器怎样编写C语言工程&#xff0c;使用按键中断将数字显示在七段数码管上呢&#xff1f; A&#xff1a;基本原理&#xff1a;主程序需要首先调用子程序set_A9_IRQ_stack()初始化IRQ模式的ARM A9堆栈指针&#xff1b;然后主程序调用子程序config_GIC…...

dm8在Linux环境安装精简步骤说明(2024年12月更新版dm8)

dm8在Linux环境安装详细步骤 - - 2025年1月之后dm8 环境介绍1 修改操作系统资源限制2 操作系统创建用户3 操作系统配置4 数据库安装5 初始化数据库6 实例参数优化7 登录数据库配置归档与备份8 配置审计9 创建用户10 屏蔽关键字与数据库兼容模式11 jdbc连接串配置12 更多达梦数据…...

Nginx部署的前端项目刷新404问题

1&#xff0c;查看问题 我部署的81端口是监听tlias项目的&#xff0c;我直接访问端口页面可以出现内容。 我在浏览器舒服端口之后回车&#xff0c;会重定向页面。但是我在重定向之后的页面刷新浏览器就会出现404的问题。 下面是刷新浏览器后的效果 2&#xff0c;在nginx.cnf …...

H2 Database安装部署

H2 Database H2 Database官网 H2 中文文档 安装部署H2 java版本要高于java 11 ## 下载java21 wget https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz[rootlocalhost ~]# tar xf jdk-21_linux-x64_bin.tar.gz -C /usr/local/ [rootlocalhost ~]# vi…...

Day40:列表的排序

在 Python 中&#xff0c;排序是处理列表数据时常用的一种操作。排序可以帮助我们按照一定的规则&#xff08;如升序或降序&#xff09;对列表中的元素进行排列。Python 提供了内置的排序方法 sort() 和 sorted() 来实现这一功能。 1. 使用 sort() 方法排序 1.1 sort() 方法简…...

TypeScript进阶(三):断言

文章目录 一、前言二、类型断言2.1 利用 as 实现断言2.2 利用 <> 实现断言2.3 应用示例2.3.1 如果 A&#xff0c;B 如果是类并且有继承关系2.3.2 如果 A&#xff0c;B 如果是类&#xff0c;但没有继承关系2.3.3 如果 A 是类&#xff0c;B 是接口&#xff0c;并且 A 类实现…...

塔罗牌(基础):大阿卡那牌

塔罗牌&#xff08;基础&#xff09; 大啊卡那牌魔术师女祭司皇后皇帝教皇恋人战车力量隐士命运之轮正义吊人死神节制恶魔高塔星星月亮太阳审判世界 大啊卡那牌 魔术师 作为一个起点&#xff0c;象征&#xff1a;意识行动和创造力。 一个【显化】的概念&#xff0c;即是想法变…...

微服务(一)

文章目录 项目地址一、微服务1.1 分析User的Domian Verb和Nouns 二、运行docker和k8s2.1 Docker1. 编写dockerfile2. 创建docker image3. 运行docker使用指定端口4. 查看当前运行的镜像5. 停止当前所有运行的docker6. 删除不用的docker images7. 将本地的image上传到hub里 2.2 …...

JAVA(SpringBoot)集成Kafka实现消息发送和接收。

SpringBoot集成Kafka实现消息发送和接收。 一、Kafka 简介二、Kafka 功能三、POM依赖四、配置文件五、生产者六、消费者 君子之学贵一&#xff0c;一则明&#xff0c;明则有功。 一、Kafka 简介 Kafka 是由 Apache 软件基金会开发的一个开源流处理平台&#xff0c;最初由 Link…...

Oracle之开窗函数使用

开窗函数是数据开发面试的必知必会&#xff0c;必须认真对待&#xff0c;上难度&#xff1a; 开窗函数语法格式如下&#xff0c;一共五部分&#xff1a; ①函数(a)over(②<partition by b> ③<order by c> ④<windowing_clause> ⑤开窗范围)1、函数&#xf…...

mysql_store_result的概念和使用案例

mysql_store_result() 是 MySQL C API 中的一个函数&#xff0c;用于检索一个完整的结果集到一个客户端。当执行一个查询&#xff08;通常是 SELECT 查询&#xff09;并希望处理所有返回的数据时&#xff0c;可以使用此函数。 概念 mysql_store_result() 函数的原型如下&…...

【大数据】数据治理浅析

在数字化时代&#xff0c;数据作为企业的核心资产&#xff0c;其管理和利用显得尤为关键。数据治理&#xff0c;作为数据管理的重要组成部分&#xff0c;旨在确保数据的准确性、一致性、安全性和可用性。本文将从数据治理的基本概念、应用场景、必要性、需求分析等方面出发&…...

第 25 场 蓝桥月赛

4.喜糖摆放【算法赛】 - 蓝桥云课 问题描述 在过年时&#xff0c;蓝桥村的孩子们充满活力&#xff0c;他们化身为捣蛋鬼&#xff0c;挨家挨户寻讨喜糖。他们一共收到了N颗糖&#xff0c;每颗糖的甜度各不相同&#xff0c;第i颗糖的甜度为Ai。 然而&#xff0c;如何分配这些喜…...

LigerUI在MVC模式下的响应原则

LigerUI是基于jQuery的UI框架&#xff0c;故他也是遵守jQuery的开发模式&#xff0c;但是也具有其特色的侦听函数&#xff0c;那么当LigerUI作为View层的时候&#xff0c;他所发送后端的必然是表单的数据&#xff0c;在此我们以俩个div为例&#xff1a; {Layout "~/View…...

Vue2下篇

插槽&#xff1a; 基本插槽&#xff1a; 普通插槽&#xff1a;父组件向子组件传递静态内容。基本插槽只能有一个slot标签&#xff0c;因为这个是默认的位置&#xff0c;所以只能有一个 <!-- ParentComponent.vue --> <template> <ChildComponent> <p>…...