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

【Linux系统编程】:进程池(简易版)

目录

1.制作游戏菜单

 2.对管道进行描述和组织

3.初始化管道

3.1子进程执行任务slaver()

3.2检查管道是否创建有误 

4.父进程向管道写入(控制子进程执行任务)

5.清理资源

修改初始化管道代码

6.完整代码:


1.制作游戏菜单

我们利用管道的原理,创建一个简易的进程池,其中父进程向管道写入“任务码”,子进程从管道中读取 “任务码”,并根据任务码执行对应的任务。

我们先模拟一个简易的游戏任务菜单,

void Menu()
{std::cout << "################################################" << std::endl;std::cout << "# 1. 刷新日志             2. 刷新出来野怪        #" << std::endl;std::cout << "# 3. 检测软件是否更新      4. 更新用的血量和蓝量  #" << std::endl;std::cout << "#                         0. 退出               #" << std::endl;std::cout << "#################################################" << std::endl;
}

根据菜单中的功能,我们简略模拟对应的函数 :

typedef void (*task_t)();
void task1()
{std::cout << "lol 刷新日志" << std::endl;
}
void task2()
{std::cout << "lol 更新野区,刷新出来野怪" << std::endl;
}
void task3()
{std::cout << "lol 检测软件是否更新,如果需要,就提示用户" << std::endl;
}
void task4()
{std::cout << "lol 用户释放技能,更新用的血量和蓝量" << std::endl;
}

 我们需要将这些函数组织起来,利用下标去管理,

void LoadTask(std::vector<task_t> *tasks)
{tasks->push_back(task1);tasks->push_back(task2);tasks->push_back(task3);tasks->push_back(task4);
}

当我们调用菜单中的某个功能, 只要定义一个

std::vector<task_t> tasks;//任务列表

然后加载任务(调用LoadTask()),就可根据下标使用不同的功能,比如要想刷新野区野怪(任务2),只需要调用tasks[1]既可。任务标号和vector下标的映射关系:任务标号 - 1 = vector下标。

 2.对管道进行描述和组织

 假设我们要创建十个管道,每个管道对应的子进程的pid要保存:

//先描述:
class channel
{
public:channel(int cmdfd,pid_t slaverid,std::string &processname):_cmdfd(cmdfd),_slaverid(slaverid),_processname(processname){}
public:int _cmdfd;                 //发送任务的文件描述符pid_t _slaverid;            //子进程的pidstd::string _processname;   //子进程的名字——方便打印日志
};

然后定义一个vector将这些管道管理起来,

//再组织
std::vector<channel> channels;

3.初始化管道

我们要创建十个子进程,并初始化十个管道,其中要保存子进程的pid(父进程后续要回收),子进程读取管道的文件描述符(通过读取管道接收父进程写入管道的任务码),以及给子进程编号(起名)并保存其编号(方便管理)。

const int processnum = 10;//进程数
void InitProcessPool(std::vector<channel>* channels)
{for(int i = 0;i < processnum;i++){//1.1 创建管道int pipefd[2];int n = pipe(pipefd);//创建成功返回0assert(!n);//如果n不是0管道就创建失败(void)n;//1.2 创建子进程并构建单向通信渠道pid_t id = fork();if(id == 0)//child{close(pipefd[1]);//slaver(pipefd[0]);//一般用dup2取代这种写法dup2(pipefd[0],0);//用标准输入替换读端 close(pipefd[0]);slaver();//这样,以后读取父进程的“任务码”,只需要从标准输入中读std::cout << "process:" << getpid << "quit" <<std::endl;exit(0);}//fatherclose(pipefd[0]);//构建channel字段(名字)std::string name = "process--" + std::to_string(i);channels->push_back(channel(pipefd[1],id,name));}
}

3.1子进程执行任务slaver()

其中slaver()表示子进程要执行的具体的任务,当子进程调用到slaver时,如果父进程没有发送“任务码”,子进程会进入阻塞状态等待父进程写入。

void slaver()
{//read(0)int cnt = 5;while(true){int cmdcode = 0;int n = read(0,&cmdcode,sizeof(int));if(n == sizeof(cmdcode)){//执行cmdcode对应的任务std::cout <<"slaver say@ get a command: "<< getpid() << " : cmdcode: "<< cmdcode << std::endl;if(cmdcode >= 0 && cmdcode < tasks.size()){tasks[cmdcode]();//函数指针的解引用符号可以省略}}if(n == 0) break;}
}

3.2检查管道是否创建有误 

创建管道后,我们还可以将所有管道的信息打印出来,间接检查一下管道是否创建有误,

void debug(const std::vector<channel> &channels)
{for(const auto c:channels){std::cout << "cmdfd:" << c._cmdfd << " slaverid:" << c._slaverid << " processname:" << c._processname << std::endl;}
}

4.父进程向管道写入(控制子进程执行任务)

 我们可以通过随机安排进程执行任务,通过输入指定安排进程执行任务等方式,控制子进程执行任务。

void ctrlSlaver(const std::vector<channel> &channels)
{int which = 0;while(true){int select = 0;Menu();std::cout << "please enter@";std::cin >> select;if(select <= 0 || select > 4) break;//2.1 选择任务//int cmdcode = rand()%tasks.size();//用随机数模拟"选择"的过程int cmdcode = select - 1;//2.2 选择进程//int processpos = rand()%channels.size();//2.3 发送任务std::cout << "father say: " << " cmdcode is " <<cmdcode << ",already sendto " << channels[which]._slaverid << ",process name: " << channels[which]._processname << std::endl;write(channels[which]._cmdfd,&cmdcode,sizeof(cmdcode));which++;which %= channels.size();}
}

5.清理资源

我们创建了10个进程,就要回收这些进程。对于管道,我们只要关闭写端,读端的进程就会退出。

 
void QuitProcess(const vector<channel> &channels)
{for (const auto e : channels) {close(e._cmdfd);  //写端waitpid(e._slaverid, nullptr, 0);}
}

如果我们按照这样写,程序运行时会报错。因为我们在初始化管道时,理想中创建的管道如下图1:

子进程和附近之间的读写端是一一对应的,但实际上,子进程会继承父进程的写段,所以创建的子进程越多,最后创建的子进程继承的读端(也就是父进程向管道中“读”对应的文件描述符就会越多)就会越多,就会造成子进程的读端对应多个写端的情况,真实情况如上图2。

所以我们要对上面初始化管道的代码进行一个修改:

修改初始化管道代码

void InitProcessPool(std::vector<channel>* channels)
{//确保每一个子进程都只有一个写端:将父进程的写端记录下来,在子进程中关闭即可std::vector<int> oldfd;//记录父进程的写端for(int i = 0;i < processnum;i++){//1.1 创建管道int pipefd[2];int n = pipe(pipefd);//创建成功返回0assert(!n);//如果n不是0管道就创建失败(void)n;//1.2 创建子进程并构建单向通信渠道pid_t id = fork();if(id == 0)//child{for(auto fd:oldfd) close(fd);//关闭之前父进程的写端close(pipefd[1]);//slaver(pipefd[0]);//一般用dup2取代这种写法dup2(pipefd[0],0);//用标准输入替换读端 close(pipefd[0]);slaver();//这样,以后读取父进程的“任务码”,只需要从标准输入中读std::cout << "process:" << getpid << "quit" <<std::endl;exit(0);}//fatherclose(pipefd[0]);//构建channel字段(名字)std::string name = "process--" + std::to_string(i);channels->push_back(channel(pipefd[1],id,name));oldfd.push_back(pipefd[1]);}
}

这样就没有问题了。

6.完整代码:

Task.hpp:

#pragma once
#include <iostream>
#include <functional>
#include <vector>
typedef void (*task_t)();void task1()
{std::cout << "lol 刷新日志" << std::endl;
}
void task2()
{std::cout << "lol 更新野区,刷新出来野怪" << std::endl;
}
void task3()
{std::cout << "lol 检测软件是否更新,如果需要,就提示用户" << std::endl;
}
void task4()
{std::cout << "lol 用户释放技能,更新用的血量和蓝量" << std::endl;
}void LoadTask(std::vector<task_t> *tasks)
{tasks->push_back(task1);tasks->push_back(task2);tasks->push_back(task3);tasks->push_back(task4);
}

ProcessPool.cc 

#include "Task.hpp" //后缀hpp表示头文件和源文件中的内容不分开写,比如函数的声明和定义放在同一个文件内
#include <string>
#include <unistd.h>
#include <cstdlib>
#include <ctime>
#include <cassert>
#include <sys/types.h>
#include <sys/wait.h>
const int processnum = 10;//进程数
std::vector<task_t> tasks;//任务列表//先描述:
class channel
{
public:channel(int cmdfd,pid_t slaverid,std::string &processname):_cmdfd(cmdfd),_slaverid(slaverid),_processname(processname){}
public:int _cmdfd;                 //发送任务的文件描述符pid_t _slaverid;            //子进程的pidstd::string _processname;   //子进程的名字——方便打印日志
};
void slaver()
{//read(0)int cnt = 5;while(true){int cmdcode = 0;int n = read(0,&cmdcode,sizeof(int));if(n == sizeof(cmdcode)){//执行cmdcode对应的任务std::cout <<"slaver say@ get a command: "<< getpid() << " : cmdcode: "<< cmdcode << std::endl;if(cmdcode >= 0 && cmdcode < tasks.size()){tasks[cmdcode]();//函数指针的解引用符号可以省略}}if(n == 0) break;}
}
//输入:const &
//输出: *
//输入输出:&
void InitProcessPool(std::vector<channel>* channels)
{//确保每一个子进程都只有一个写端:将父进程的写端记录下来,在子进程中关闭即可std::vector<int> oldfds;//记录父进程的写端for(int i = 0;i < processnum;i++){//1.1 创建管道int pipefd[2];int n = pipe(pipefd);//创建成功返回0assert(!n);//如果n不是0管道就创建失败(void)n;//1.2 创建子进程并构建单向通信渠道pid_t id = fork();if(id == 0)//child{std::cout << "child: " << getpid() << " close history fd: ";for(auto fd : oldfds) {std::cout << fd << " ";close(fd);}std::cout << "\n";close(pipefd[1]);//slaver(pipefd[0]);//一般用dup2取代这种写法dup2(pipefd[0],0);//用标准输入替换读端 close(pipefd[0]);slaver();//这样,以后读取父进程的“任务码”,只需要从标准输入中读std::cout << "process-id:" << getpid() << " quit" <<std::endl;exit(0);}//fatherclose(pipefd[0]);//构建channel字段(名字)std::string name = "process--" + std::to_string(i);channels->push_back(channel(pipefd[1],id,name));oldfds.push_back(pipefd[1]);sleep(1);}
}
void debug(const std::vector<channel> &channels)
{for(const auto c:channels){std::cout << "cmdfd:" << c._cmdfd << " slaverid:" << c._slaverid << " processname:" << c._processname << std::endl;}
}
void Menu()
{std::cout << "################################################" << std::endl;std::cout << "# 1. 刷新日志             2. 刷新出来野怪        #" << std::endl;std::cout << "# 3. 检测软件是否更新      4. 更新用的血量和蓝量  #" << std::endl;std::cout << "#                         0. 退出               #" << std::endl;std::cout << "#################################################" << std::endl;
}
void ctrlSlaver(const std::vector<channel> &channels)
{int which = 0;while(true){int select = 0;Menu();std::cout << "please enter@";std::cin >> select;if(select <= 0 || select > 4) break;//2.1 选择任务//int cmdcode = rand()%tasks.size();//用随机数模拟"选择"的过程int cmdcode = select - 1;//2.2 选择进程//int processpos = rand()%channels.size();//2.3 发送任务std::cout << "father say: " << " cmdcode is " <<cmdcode << ",already sendto " << channels[which]._slaverid << ",process name: " << channels[which]._processname << std::endl;write(channels[which]._cmdfd,&cmdcode,sizeof(cmdcode));which++;which %= channels.size();}
}
void QuitProcess(const std::vector<channel> &channels)
{// //关闭父进程所有的写端,子进程就会退出进入僵尸状态// for(auto &c : channels) close(c._cmdfd);// //sleep(5);// //回收所有子进程// for(auto &c : channels) waitpid(c._slaverid,nullptr,0);// //sleep(5);for (const auto e : channels) {close(e._cmdfd);  //写端waitpid(e._slaverid, nullptr, 0);}
}
int main()
{LoadTask(&tasks);srand(time(nullptr)^getpid()^1023); // 种一个随机数种子//再组织std::vector<channel> channels;//1.初始化InitProcessPool(&channels);//testdebug(channels);//2.开始控制子进程ctrlSlaver(channels);//3.清理QuitProcess(channels);return 0;
}

相关文章:

【Linux系统编程】:进程池(简易版)

目录 1.制作游戏菜单 2.对管道进行描述和组织 3.初始化管道 3.1子进程执行任务slaver() 3.2检查管道是否创建有误 4.父进程向管道写入&#xff08;控制子进程执行任务&#xff09; 5.清理资源 修改初始化管道代码 6.完整代码&#xff1a; 1.制作游戏菜单 我们利用管道…...

uniapp实现小程序的版本更新

参考官方文档&#xff1a;uni.getUpdateManager() | uni-app官网 uni.getUpdateManager()是uniapp框架提供的一个API&#xff0c;用于管理小程序的版本更新。这个API返回一个全局唯一的版本更新管理器对象&#xff0c;该对象可以用于检测新版本、下载新版本以及提示用户重启应…...

嵌入式QT学习第4天:Qt 信号与槽

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 本章思维导图如下&#xff1a; 不使用 Qt Designer 的方式进行开发&#xff0c;用代码绘界面&#xff0c;可以锻炼我们的布局能力&#xff0c;和代码逻辑能力&#x…...

`asyncio.wait` 和 `asyncio.gather` 的区别

asyncio.wait 和 asyncio.gather 的区别 1. asyncio.wait2. asyncio.gather主要区别总结 在Python的异步编程中&#xff0c;asyncio.wait 和 asyncio.gather 都是用于等待多个异步任务完成的工具&#xff0c;但它们在功能和使用方式上有一些关键的区别。本文将详细解释这两个函…...

【JavaEE】多线程(2)

一、线程安全 1.1 线程安全的概念 线程是随机调度执行的&#xff0c;如果多线程环境下的程序运行的结果符合我们预期则说明线程安全&#xff0c;反之&#xff0c;如果遇到其他结果甚至引起了bug则说明线程不安全 1.2 经典例子与解释 下面举一个经典的线程不安全的例子&…...

虚拟地址空间与物理内存(Linux系统)

个人主页&#xff1a;敲上瘾-CSDN博客 个人专栏&#xff1a;Linux学习、游戏、数据结构、c语言基础、c学习、算法 目录 问题引入 一、什么是虚拟内存 二、虚拟内存的描述与组织 三、页表的优势 四、虚拟内存区域划分 问题引入 为引入今天的话题&#xff0c;我们先来看下面…...

iOS Arkit机器学习相关

最近在搞追踪运动物体&#xff0c;然后Arkit识别3d模型和图片&#xff0c;静止状态还不错&#xff0c;运动时候效果还是有点差&#xff0c;所以搞了下苹果的CoreML&#xff0c;苹果官网也有一些训练好的模型 苹果模型列表&#xff0c;自己参考或者使用&#xff0c;提供一个数据…...

Maven CMD命令

打包测试命令 在当前文件中 >mvn clean package -D maven.test.skiptrue 基本命令 mvn clean 清理目标目录&#xff08;target&#xff09;中的输出文件。 mvn compile 编译主源代码路径&#xff08;src/main/java&#xff09;下的 Java 代码。 mvn test-compile 编译测试源…...

DM-VIO(ROS)+t265配置运行记录(ubuntu18.04+ros melodic)

在工作中需要对DM-VIO算法进行测试&#xff0c;于是配置并记录了一下&#xff1a; 首先运行ros接口的dm-vio&#xff0c;一定要先配置源码 https://github.com/lukasvst/dm-vio在这个网址把源码下载下来并解压&#xff0c;并安装一下依赖&#xff1a; sudo apt-get install …...

DETR:一种新颖的端到端目标检测与分割框架

DETR&#xff1a;一种新颖的端到端目标检测与分割框架 摘要&#xff1a; 随着深度学习技术的发展&#xff0c;目标检测和图像分割任务取得了显著的进步。然而&#xff0c;传统的基于区域提名的方法在处理这些问题时存在一定的局限性。为此&#xff0c;Facebook AI Research&am…...

Android 输入事件拦截机制

Keyboard产生按键事件后&#xff0c;会通过notifyKey开始传递&#xff1a; frameworks\native\services\inputflinger\InputDispatcher.cpp void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {...uint32_t policyFlags args->policyFlags;//只关注policyFlags…...

【Figma】中文版安装

一、软件安装包下载 打开官网链接https://www.figma.com/downloads/下载相应安装包 或使用我已下载好的链接&#xff1a; FigmaSetup.exe 链接: https://pan.baidu.com/s/113eQ8JRETdeOwUp2B3uieA?pwd4vep 二、安装流程 1.点击安装包 2.选择在浏览器登录 3.输入账号密码&a…...

SolarCube: 高分辨率太阳辐照预测基准数据集

太阳能作为清洁能源在减缓气候变化中的作用日益凸显&#xff0c;其稳定的供应对电网管理至关重要。然而&#xff0c;太阳辐照受云层和天气变化的影响波动较大&#xff0c;给光伏电力的管理带来挑战&#xff0c;尤其是在调度、储能和备用系统管理方面。因此&#xff0c;精确的太…...

arkTS:持久化储存UI状态的基本用法(PersistentStorage)

arkUI&#xff1a;持久化储存UI状态的基本用法&#xff08;PersistentStorage&#xff09; 1 主要内容说明2 例子2.1 持久化储存UI状态的基本用法&#xff08;PersistentStorage&#xff09;2.1.1 源码1的相关说明2.1.1.1 数据存储2.1.1.2 数据读取2.1.1.3 动态更新2.1.1.4 显示…...

【Canvas与雷达】点鼠标可暂停金边蓝屏雷达显示屏

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>点鼠标可暂停金边蓝屏雷达显示屏 Draft1</title><style typ…...

第二部分shell----二、shell 条件测试

一、基本语法 在shell程序中&#xff0c;用户可以使用测试语句来测试指定的条件表达式的条件的真或假。当指定的条件为 真时&#xff0c;整个条件测试的返回值为0&#xff1b;反之&#xff0c;如果指定的条件为假&#xff0c;则条件测试语句的返回值为非0值。 1.test<测试表…...

node修改文件名称

node修改名称 var fs require(fs); const events require(events); var path require(path);init(); function init() {//要遍历的文件夹所在的路径const dirPath path.resolve(__dirname, "data");//遍历目录fileDisplay(dirPath); }/*** 文件遍历* param dirP…...

Vue教程|搭建vue项目|Vue-CLI新版脚手架

一、安装Node环境 安装Node及Npm环境 Node下载地址:Node.js — Run JavaScript EverywhereNode.js is a JavaScript runtime built on Chromes V8 JavaScript engine.https://nodejs.org/en/ 安装完成后,检查安装是否成功,并检查版本,命令如下: node -v npm -v mac@Macd…...

Java设计模式

Java设计模式 一、观察者设计模式1.1 概述1.2 结构1.3 特点1. 优点2. 缺点3. 使用场景 1.4 JDK中的实现1. Observable 类2. Observer 接口3. 例子 二、模板设计模式三、单例设计模式一、懒汉式单例二、饿汉式单例 四、Builder模式4.1 概述4.2 结构4.3 具体实现4.4 使用场景 一、…...

java 接口防抖

防抖&#xff1a;防止重复提交 在Web系统中&#xff0c;表单提交是一个非常常见的功能&#xff0c;如果不加控制&#xff0c;容易因为用户的误操作或网络延迟导致同一请求被发送多次&#xff0c;进而生成重复的数据记录。要针对用户的误操作&#xff0c;前端通常会实现按钮的l…...

[C++并发编程] 线程基础

线程发起 最简单的发起一个线程。 void thread_work(std::string str) {std::cout << "str: " << std << std::endl; } //初始化并启动一个线程 std::thread t1(thread, wangzn2016); 线程等待&#xff1a; 线程发起后&#xff0c;可能新的线…...

基于若依框架和Vue2 + Element-UI 实现图片上传组件的重写与优化

背景 在使用 若依分离版Element-UI 的图片上传组件时,需要根据业务需求进行定制化处理,比如: 需要传递额外的业务参数到后端需要对上传路径进行修改需要对上传组件进行样式定制 实现步骤 1. 创建本地组件 首先在业务模块下创建本地的图片上传组件: src/views/xxx/compone…...

自定义类型: 结构体、枚举 、联合

目录 结构体 结构体类型的声明 匿名结构体 结构的自引用 结构体变量的定义和初始化 结构体成员变量的访问 结构体内存对齐 结构体传参 位段 位段类型的声明 位段的内存分配 位段的跨平台问题 位段的应用 枚举 枚举类型的定义 枚举的优点 联合体(共用体) 联合…...

力扣98:验证二叉搜索树

给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左 子树 只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例 1&#xff1a; 输入…...

Java Stream reduce 函数,聚合数据

Stream.reduce() 是 Stream 的一个聚合方法&#xff0c;它可以把一个 Stream 的所有元素按照自定义聚合逻辑&#xff0c;聚合成一个结果。 先看一个简单数字求和&#xff1a; public class Main {public static void main(String[] args&#xff09;{int sum Stream.of(1, 2…...

npm install -g@vue/cli报错解决:npm error code ENOENT npm error syscall open

这里写目录标题 报错信息1解决方案 报错信息2解决方案 报错信息1 使用npm install -gvue/cli时&#xff0c;发生报错&#xff0c;报错图片如下&#xff1a; 根据报错信息可以知道&#xff0c;缺少package.json文件。 解决方案 缺什么补什么&#xff0c;这里我们使用命令npm…...

阿里云服务器(centos7.6)部署前后端分离项目(MAC环境)

Jdk17安装部署 下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/ 选择自己需要的jdk版本进行下载。 通过mac终端scp命令上传下载好的jdk17到服务器的/usr/local目录下 scp -r Downloads/jdk-17.0.13_linux-x64_bin.tar.gz 用户名服务器ip地址:/us…...

【机器学习】机器学习基础

什么是机器学习&#xff1f; 机器学习&#xff08;Machine Learning, ML&#xff09;是一种人工智能&#xff08;AI&#xff09;的分支&#xff0c;指计算机通过数据学习规律并做出预测或决策&#xff0c;而无需明确编程。它的核心目标是让机器能够从经验中学习&#xff0c;逐…...

BUUCTF—Reverse—Java逆向解密(10)

程序员小张不小心弄丢了加密文件用的秘钥&#xff0c;已知还好小张曾经编写了一个秘钥验证算法&#xff0c;聪明的你能帮小张找到秘钥吗&#xff1f; 注意&#xff1a;得到的 flag 请包上 flag{} 提交 需要用专门的Java反编译软件:jd-gui 下载文件&#xff0c;发现是个class文…...

基于JSP+MySQL的网上招聘系统的设计与实现

摘要 在这样一个经济飞速发展的时代&#xff0c;人们的生存与生活问题已成为当代社会需要关注的一个焦点。对于一个刚刚 踏入社会的年轻人来说&#xff0c;他对就业市场和形势了解的不够详细&#xff0c;同时对自己的职业规划也很模糊&#xff0c;这就导致大量的 时间被花费在…...

js 中 file 文件 应用

文章目录 文件上传File 对象基本属性文件上传大文件上传文件格式校验通过 type 属性校验图片格式通过文件名扩展名校验 文件解析一、处理图片文件流&#xff08;以 Blob 格式接收文件流为例&#xff09;二、处理文本文件流三、处理 PDF 文件流&#xff08;借助 PDF.js 库来展示…...

Java 泛型详细解析

泛型的定义 泛型类的定义 下面定义了一个泛型类 Pair&#xff0c;它有一个泛型参数 T。 public class Pair<T> {private T start;private T end; }实际使用的时候就可以给这个 T 指定任何实际的类型&#xff0c;比如下面所示&#xff0c;就指定了实际类型为 LocalDate…...

「Mac畅玩鸿蒙与硬件33」UI互动应用篇10 - 数字猜谜游戏

本篇将带你实现一个简单的数字猜谜游戏。用户输入一个数字&#xff0c;应用会判断是否接近目标数字&#xff0c;并提供提示“高一点”或“低一点”&#xff0c;直到用户猜中目标数字。这个小游戏结合状态管理和用户交互&#xff0c;是一个入门级的互动应用示例。 关键词 UI互…...

自然语言处理期末试题汇总

建议自己做&#xff0c;写完再来对答案。答案可能存在极小部分错误&#xff0c;不保证一定正确。 一、选择题 1-10、C A D B D B C D A A 11-20、A A A C A B D B B A 21-30、B C C D D A C A C B 31-40、B B B C D A B B A A 41-50、B D B C A B B B B C 51-60、A D D …...

记录Threadlocal使用

编写ThreadLocal工具类 package com.jjking.jplan.context;public class BaseContext<T> {public static final ThreadLocal threadLocal new ThreadLocal();//存储用户public static void set(Object t) {threadLocal.set(t);}//获取用户public static <T> T ge…...

利用 SpringBoot 开发的新冠密接者跟踪系统:医疗机构疫情防控辅助方案

摘 要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自古…...

vue 2 父组件根据注册事件,控制相关按钮显隐

目标效果 我不注册事件&#xff0c;那么就不显示相关的按钮 注册了事件&#xff0c;才会显示相关内容 实现思路 组件在 mounted 的时候可以拿到父组件注册监听的方法 拿到这个就可以做事情了 mounted() {console.log(this.$listeners, this.$listeners);this.show.search !…...

【深度学习基础】一篇入门模型评估指标(分类篇)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;深度学习_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. 模…...

hls视频流学习

hls格式播放的依赖安装&#xff1a; <!-- 新增hls播放库 -->npm install hls.js 组件封装&#xff1a; <template><div class"hls-player-cls"><video ref" video" controls style"width: 100%; max-width: 800px;">…...

【electron-vite】搭建electron+vue3框架基础

一、拉取项目 electron-vite 中文文档地址&#xff1a; https://cn-evite.netlify.app/guide/ 官网网址&#xff1a;https://evite.netlify.app/ 版本 vue版本&#xff1a;vue3 构建工具&#xff1a;vite 框架类型&#xff1a;Electron JS语法&#xff1a;TypeScript &…...

第三方Express 路由和路由中间件

文章目录 1、Express 应用使用回调函数的参数&#xff1a; request 和 response 对象来处理请求和响应的数据。2、Express路由1.路由方法2.路由路径3.路由处理程序 3. 模块化路由4. Express中间件1.中间件简介2.中间件分类3.自定义中间件 1、Express 应用使用回调函数的参数&am…...

WPF 常用的5个布局容器控件介绍

1. Grid Grid 是最常用的布局容器之一&#xff0c;它允许开发者以表格的方式对控件进行组织和布局。Grid 使用行和列来划分区域&#xff0c;可以精确控制控件的位置和大小。 特点&#xff1a; 行列定义&#xff1a;Grid 使用 RowDefinitions 和 ColumnDefinitions 来定义行和…...

【JAVA] 杂谈: java中的拷贝(克隆方法)

这篇文章我们来介绍什么是拷贝&#xff0c;并且实现浅拷贝到深拷贝。 目录 一、浅拷贝 1.1 clone 方法 1.2 实现浅拷贝&#xff1a; 1.2.1 重写 clone方法 1.2.2 实现接口 Cloneable 1.2.3 调用克隆方法 1.2.4 原理图&#xff1a;​ 1.3 浅拷贝的不足 1.3.1 增加引用…...

同时多平台git配置:GitHub和Gitee生成不同的SSH Key

文章目录 GitHub和Gitee生成不同的SSH Key步骤1&#xff1a;生成SSH Key步骤2&#xff1a;配置SSH配置文件步骤3&#xff1a;查看SSH公钥步骤4&#xff1a;将SSH公钥添加到GitHub和Gitee步骤5&#xff1a;测试SSH连接步骤6&#xff1a;添加remote远程库 GitHub和Gitee生成不同的…...

flink1.6集成doris,并从mysql同步数据到doris

使用 Apache Flink 1.6 集成 Doris&#xff0c;并从 MySQL 同步数据到 Doris 是一个复杂的任务&#xff0c;但可以通过以下步骤实现。Doris 是一个现代化的 MPP&#xff08;大规模并行处理&#xff09;SQL 数据库&#xff0c;支持实时分析和交互式查询。Flink 可以作为实时数据…...

手搓一个不用中间件的分表策略

场景&#xff1a;针对一些特别的项目&#xff0c;不用中间件&#xff0c;以月为维度进行分表&#xff0c;代码详细设计方案 1. 定义分片策略 首先&#xff0c;定义一个分片策略类&#xff0c;用于决定数据存储在哪个分表中 import java.time.LocalDate; import java.time.fo…...

AI前景分析展望——GPTo1 SoraAI

引言 人工智能&#xff08;AI&#xff09;领域的飞速发展已不仅仅局限于学术研究&#xff0c;它已渗透到各个行业&#xff0c;影响着从生产制造到创意产业的方方面面。在这场技术革新的浪潮中&#xff0c;一些领先的AI模型&#xff0c;像Sora和OpenAI的O1&#xff0c;凭借其强大…...

损失函数Hinge Loss介绍

Hinge Loss 是一种损失函数,广泛用于 支持向量机(SVM, Support Vector Machine) 和一些分类问题中。它特别适合用于 二分类问题,主要目标是让模型的预测值(通常是经过线性变换的原始分数)与真实标签之间的间隔尽可能大,从而提高分类的鲁棒性。 Hinge Loss 的定义 Hinge…...

多维高斯分布(Multivariate Gaussian Distribution)以及协方差矩阵:解析与应用

多维高斯分布&#xff1a;全面解析及其应用 1. 什么是多维高斯分布&#xff1f; 多维高斯分布&#xff08;Multivariate Gaussian Distribution&#xff09;&#xff0c;也称多元正态分布&#xff0c;是高斯分布在高维空间中的推广。它描述了随机向量 ( x ( x 1 , x 2 , … ,…...

前端开发常用快捷键

浏览器 ctrl e 光标定位在搜索框ctrl r 刷新ctrl t 新打开tabctrl tab 向右切换tabctrl shift tab 向左切换tab vscode ctrl p 全局搜索文件ctrl f 当前文件搜索alt 光标左键向下拖动&#xff1a;竖向选中多行文本ctrl b 切换侧边栏显示隐藏ctrl shift p 显示命…...