基于 Quartz 的调度中心

news/2024/4/30 0:29:43/文章来源:https://blog.csdn.net/SevenLitile/article/details/126813290

需求

  • 服务使用集群部署(多Pod)
  • 基础服务提供调度任务注册,删除,查看的功能
  • 尽可能减少客户端的使用成本
  • 开发工作量尽可能少,成本尽可能小

基于以上的需求,设计如下,调度中心非独立部署,集成在base服务中。客户端目前属于同一个项目,直接使用公共模块的代码,非sdk使用。

客户端接入调度中心,只需2步。

  1. 使用公共模块的服务,调度任务注册
  2. 实现公共模块的job接口,注册中心会按照客户端提供信息,触发任务
  3. 服务端与客户端的交互使用http通讯,由k8s提供的域名调用,路由逻辑由k8s ingress 提供(默认多pod,循环调用)
  4. 服务端不保证客户端执行结束,只保证调度任务正确触发,客户端任务为异步执行

 实现demo如下

  • springboot,依赖
    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.18</version><scope>provided</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

yaml 配置

server:port: 8082# 应用名称
spring:application:name: quartz-demoquartz:job-store-type: jdbcjdbc:# 是否自动初始化quartz的表结构initialize-schema: never#相关属性配置properties:org:quartz:jobStore:# 使用的数据源名称dataSource: quartzDataSource# 设置为“true”以打开群集功能,多个quartz实力必须打开isClustered: trueclass: org.quartz.impl.jdbcjobstore.JobStoreTXtablePrefix: QRTZ_# 标准jdbc数据库代理driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegatedatasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=falseusername: rootpassword: 123456

客户端主要使用以下的代码

job 接口

package com.lq.quartzdemo.controller;/*** @author seven* @version 1.0* @description 公共job* @date 2022/9/11 14:33*/
public interface CommonJob {/*** JOB 的名字** @return*/String jobName();/*** 执行job** @param param* @return*/Object exec(Object param);
}

job 工厂

package com.lq.quartzdemo.controller;import com.google.common.util.concurrent.ThreadFactoryBuilder;
import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;/*** @author seven* @version 1.0* @description job factory* @date 2022/9/11 14:37*/
@Component
@Log4j2
public class CommonJobFactory implements ApplicationContextAware {// 任务映射private static Map<String, CommonJob> jobNameMapping = new HashMap<>();// 线程池private static ExecutorService threadPool;@Value("${schedule.core_pool_size:5}")private Integer CORE_POOL_SIZE;@Value("${schedule.max_pool_size:20}")private Integer MAX_POOL_SIZE;@Value("${schedule.queue_size:10000}")private Integer QUEUE_SIZE;public static String run(String jobName, Object param) {CompletableFuture.supplyAsync(() -> {final CommonJob commonJob = jobNameMapping.get(jobName);if (null == commonJob) {throw new RuntimeException("job not exist,please check jobName");}return commonJob.exec(param);}, threadPool).exceptionally(e -> {log.error("job exec fail,jobName={},param={},e={}", jobName, param == null ? "" : param.toString(), e);return null;});return "ack ok";}public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.initJobNameMapping(applicationContext);this.initThreadPool();}public void initThreadPool() {log.info("start CommonJobFactory.initThreadPool...");ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("batch-save-nodes-%d").build();threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, 0L,TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(QUEUE_SIZE), threadFactory, new ThreadPoolExecutor.AbortPolicy());log.info("end CommonJobFactory.initThreadPool...core_size={},max_size={},queue_size={}",CORE_POOL_SIZE, MAX_POOL_SIZE, QUEUE_SIZE);}public void initJobNameMapping(ApplicationContext applicationContext) {log.info("start CommonJobFactory.initJobNameMapping...");final Collection<CommonJob> values = applicationContext.getBeansOfType(CommonJob.class).values();for (CommonJob commonJob : values) {if (StringUtils.isEmpty(commonJob.jobName())) {log.error("job name is not null");throw new JobNameException("");}if (jobNameMapping.containsKey(commonJob.jobName())) {log.error("job name is repeat,{} and {} has the same job name [{}]",commonJob.getClass().getName(), jobNameMapping.get(commonJob.jobName()).getClass().getName(), commonJob.jobName());throw new JobNameException("");}jobNameMapping.put(commonJob.jobName(), commonJob);}log.info("end CommonJobFactory.initJobNameMapping...job_size={},jobName={}", jobNameMapping.size(), jobNameMapping.keySet());}
}

调度执行controller

package com.lq.quartzdemo.controller;import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author seven* @version 1.0* @description 公共执行逻辑模块* @date 2022/9/11 14:16*/
@RestController
@RequestMapping("common-task")
public class CommonScheController {/*** 任务执行* @param taskName* @param param*/@PostMapping("{taskName}")public String taskExec(@PathVariable("taskName") String taskName, Object param) {return CommonJobFactory.run(taskName,param);}
}

任务提交、修改、删除

package com.lq.quartzdemo.task;import lombok.Data;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;import java.util.Date;/*** @author seven* @version 1.0* @description 定时任务提交器* @date 2022/9/11 14:06*/
@Component
public class ScheTaskCommit {private RestTemplate restTemplate = new RestTemplate();@Datapublic static class ScheTaskDto {// 系统名private String appname;// 任务名private String taskName;// corn 表达式private String cronExpression;// corn 开始时间private Date startTime;// corn 结束时间private Date endTime;// 触发地址 域名private String triggerAddr;// 触发参数private String triggerParam;}public void commit(ScheTaskDto scheTaskDto) {final String s = restTemplate.postForObject("http://localhost:8082/taskReceiver/register", scheTaskDto, String.class);System.out.println(s);}public void remove(String appName, String taskName) {restTemplate.delete("http://localhost:8082/taskReceiver/remove/" + appName + "/" + taskName);}
}

服务端的代码

任务接收

package com.lq.quartzdemo.controller;import com.lq.quartzdemo.task.CommonTask;
import com.lq.quartzdemo.task.QuartzManager;
import com.lq.quartzdemo.task.ScheTaskCommit;
import org.quartz.JobDataMap;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;/*** @author seven* @version 1.0* @description base 的调度任务接收controller* @date 2022/9/11 15:57*/
@RestController
@RequestMapping("taskReceiver")
public class BaseTaskReceiver {@Resourceprivate QuartzManager quartzManager;@PutMapping("register")public void registerTask(ScheTaskCommit.ScheTaskDto request){JobDataMap jobDataMap=new JobDataMap();jobDataMap.put("beginTime",request.getStartTime());jobDataMap.put("endTime",request.getEndTime());quartzManager.addJob(request.getAppname(), request.getTaskName(),CommonTask.class,request.getCronExpression(),jobDataMap);}@DeleteMapping("{appName}/{taskName}")public void deleteTask(@PathVariable("appName") String appName,@PathVariable("taskName") String taskName){quartzManager.removeJob(taskName,appName);}@GetMapping("{appName}")public Object tasks(@PathVariable("appName") String appName){return null;}
}

任务管理器

package com.lq.quartzdemo.task;import org.quartz.*;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.HashSet;
import java.util.Set;import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;/*** @author seven* @version 1.0* @description 任务管理器* @date 2022/9/11 11:03*/
@Component
public class QuartzManager {@Autowiredprivate Scheduler sched;/*** 添加任务** @param groupName 组名* @param jobName   任务名* @param cls       class文件*/@SuppressWarnings("unchecked")public void addJob(String groupName, String jobName, @SuppressWarnings("rawtypes") Class cls, String time,JobDataMap jobDataMap) {try {//任务JobDetail jobDetail = newJob(cls).withIdentity(jobName, groupName).storeDurably().usingJobData(jobDataMap).build();// 触发器TriggerBuilder<Trigger> triggerTriggerBuilder = newTrigger();if (jobDataMap.get("beginTime") != null && jobDataMap.get("endTime") != null) {Date beginTime = (Date) jobDataMap.get("beginTime");Date endTime = (Date) jobDataMap.get("endTime");triggerTriggerBuilder.startAt(beginTime).endAt(endTime);}CronTriggerImpl trigger = (CronTriggerImpl) triggerTriggerBuilder.withIdentity(groupName + jobName, groupName).withSchedule(cronSchedule(time).withMisfireHandlingInstructionDoNothing()).build();Set<Trigger> set = new HashSet();set.add(trigger);sched.scheduleJob(jobDetail, set,true);// 启动if (!sched.isShutdown()) {sched.start();}} catch (SchedulerException e) {e.printStackTrace();}}/*** @param jobName* @param jobGroupName* @Description: 移除一个任务*/public void removeJob(String jobName, String jobGroupName) {try {TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);sched.pauseTrigger(triggerKey);// 停止触发器sched.unscheduleJob(triggerKey);// 移除触发器sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务} catch (Exception e) {throw new RuntimeException(e);}}
}

在数据库中创建quartz提供的表

#
# Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar
#
# PLEASE consider using mysql with innodb tables to avoid locking issues
#
# In your Quartz properties file, you'll need to set
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;CREATE TABLE QRTZ_JOB_DETAILS(SCHED_NAME VARCHAR(120) NOT NULL,JOB_NAME  VARCHAR(200) NOT NULL,JOB_GROUP VARCHAR(200) NOT NULL,DESCRIPTION VARCHAR(250) NULL,JOB_CLASS_NAME   VARCHAR(250) NOT NULL,IS_DURABLE VARCHAR(1) NOT NULL,IS_NONCONCURRENT VARCHAR(1) NOT NULL,IS_UPDATE_DATA VARCHAR(1) NOT NULL,REQUESTS_RECOVERY VARCHAR(1) NOT NULL,JOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);CREATE TABLE QRTZ_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,JOB_NAME  VARCHAR(200) NOT NULL,JOB_GROUP VARCHAR(200) NOT NULL,DESCRIPTION VARCHAR(250) NULL,NEXT_FIRE_TIME BIGINT(13) NULL,PREV_FIRE_TIME BIGINT(13) NULL,PRIORITY INTEGER NULL,TRIGGER_STATE VARCHAR(16) NOT NULL,TRIGGER_TYPE VARCHAR(8) NOT NULL,START_TIME BIGINT(13) NOT NULL,END_TIME BIGINT(13) NULL,CALENDAR_NAME VARCHAR(200) NULL,MISFIRE_INSTR SMALLINT(2) NULL,JOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);CREATE TABLE QRTZ_SIMPLE_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,REPEAT_COUNT BIGINT(7) NOT NULL,REPEAT_INTERVAL BIGINT(12) NOT NULL,TIMES_TRIGGERED BIGINT(10) NOT NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_CRON_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,CRON_EXPRESSION VARCHAR(200) NOT NULL,TIME_ZONE_ID VARCHAR(80),PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_SIMPROP_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,STR_PROP_1 VARCHAR(512) NULL,STR_PROP_2 VARCHAR(512) NULL,STR_PROP_3 VARCHAR(512) NULL,INT_PROP_1 INT NULL,INT_PROP_2 INT NULL,LONG_PROP_1 BIGINT NULL,LONG_PROP_2 BIGINT NULL,DEC_PROP_1 NUMERIC(13,4) NULL,DEC_PROP_2 NUMERIC(13,4) NULL,BOOL_PROP_1 VARCHAR(1) NULL,BOOL_PROP_2 VARCHAR(1) NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_BLOB_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,BLOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_CALENDARS(SCHED_NAME VARCHAR(120) NOT NULL,CALENDAR_NAME  VARCHAR(200) NOT NULL,CALENDAR BLOB NOT NULL,PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_GROUP  VARCHAR(200) NOT NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_FIRED_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,ENTRY_ID VARCHAR(95) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,INSTANCE_NAME VARCHAR(200) NOT NULL,FIRED_TIME BIGINT(13) NOT NULL,SCHED_TIME BIGINT(13) NOT NULL,PRIORITY INTEGER NOT NULL,STATE VARCHAR(16) NOT NULL,JOB_NAME VARCHAR(200) NULL,JOB_GROUP VARCHAR(200) NULL,IS_NONCONCURRENT VARCHAR(1) NULL,REQUESTS_RECOVERY VARCHAR(1) NULL,PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);CREATE TABLE QRTZ_SCHEDULER_STATE(SCHED_NAME VARCHAR(120) NOT NULL,INSTANCE_NAME VARCHAR(200) NOT NULL,LAST_CHECKIN_TIME BIGINT(13) NOT NULL,CHECKIN_INTERVAL BIGINT(13) NOT NULL,PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);CREATE TABLE QRTZ_LOCKS(SCHED_NAME VARCHAR(120) NOT NULL,LOCK_NAME  VARCHAR(40) NOT NULL,PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);commit;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_6567.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最优化 | 一维搜索与方程求根 | C++实现

文章目录参考资料前言1. 二分法求根1.1 [a,b]区间二分法求根1.1.1 原理1.1.2 C实现1.2 区间右侧无穷的二分法求根1.3 求含根区间2. 牛顿法求根2.1 原理2.2 c实现3. 梯度下降法求根3.1 c实现4. 一维搜索的区间4.1 一般一维搜索方法4.2 黄金分割法&#xff08;0.618&#xff09;4…

K8s部署SpringBoot项目简单例子

目录 前言 前提条件 正文 1. 获取镜像 2. 空运行测试生成部署yaml文件 3. 修改yaml文件&#xff0c;增加镜像拉取策略 4. 以yaml文件的方式部署springboot项目 5. 查看部署pod的状态 6. 暴露服务端口 7.通过浏览器访问服务 前言 本文通过将一个构建好的springboot的…

Linux服务器上通过miniconda安装R(2022)

安装miniconda 下载最新版miniconda wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh安装 bash Miniconda3-latest-Linux-x86_64.sh这一步骤里我们输入完命令后会有个License要读&#xff0c;一行一行读的话按Enter&#xff0c;不想读就直接输…

【uiautomation】获取微信好友名单,可指定标签 全部

前言 接到了一个需求&#xff1a;现微信有8000好友&#xff0c;需要给所有好友发送一则一样的消息。网上搜索一番后&#xff0c;发现uiautomation 可以解决该需求&#xff0c;遂有此文。这是第一篇&#xff0c;获取全部好友 代码在文章末尾&#xff0c;自取~ 微信群发消息链接 …

一个画廊的GIF动画动作英雄从80年代和90年代

你还记得那些80年代和90年代初的动作英雄吗?比如查克诺里斯、史蒂文西格尔、西尔维斯特史泰龙、让克劳德范达姆,当然还有阿诺德施瓦辛格?意大利天才设计师DavideMazuchin&;郭美雄创建了一个图文并茂的GIF画廊,名为“过去的动作英雄”,以纪念那些年轻时的经典英雄。以…

不同vlan之间实现通信

目录: 1、单臂路由实现不同vlan间通信的原理 2、单臂路由的缺陷 3、单臂路由的配置 4、三层交换 不同vlan之间实现通信 单臂路由链路类型:交换机连接主机的端口位为access链路交换机连接路由器的的端口为trunk链路子接口:路由器的物理接口可以被划分成多个逻辑接口每个子接口…

【云原生】Kubernetes CRD 详解(Custom Resource Definition)

文章目录一、概述二、定制资源1&#xff09;定制资源 和 定制控制器2&#xff09;定制控制器3&#xff09;Operator 介绍1、Operator Framework2、Operator 安装3、安装 Operator SDK4、Operator 简单使用4&#xff09;Kubernetes API 聚合层5&#xff09;声明式 APIs6&#xf…

HTML 快速入门

HTML代码是“标签化”的代码&#xff0c;把一个HTML文件视为一个文档&#xff0c;文档中有很多的标签&#xff0c;每一个标签也可以称为一个元素&#xff0c;同时每一个元素也对应一个对象&#xff0c;对象中有属性和方法。HTML的标签除了部分标签外&#xff0c;其他的都是成对…

易网防伪防窜货溯源管理系统源码

防伪防窜货和溯源系统更好用更易用&#xff0c;系统由PHPmysql开发&#xff0c;安全稳定。系统以防伪码(溯源码)为中心&#xff0c;可非常方便的为防伪码赋值产品信息&#xff0c;溯源信息。是建立防伪防窜货和溯源追踪系统的不二选择。 系统功能介绍&#xff1a; 一、防伪码管…

【RuoYi-Vue-Plus】学习笔记 40 - Validator(一)校验器对 Model 属性校验调用流程分析

文章目录前言参考目录框架集成1、Maven2、校验框架配置类 ValidatorConfig3、测试方法4、接口测试4.1、校验失败&#xff08;参数为 null&#xff09;4.2、校验成功&#xff08;参数不为 null&#xff09;执行流程分析InvocableHandlerMethod#invokeForRequestInvocableHandler…

来自邦卡的神奇扁平超级英雄插图

平面设计趋势正在相当大程度上动摇平面设计行业的各个方面。我们正在进入一个简单和最低限度的沟通模式的新时代,在这个时代中,平面设计似乎以最好的方式提供。 受平面设计形式的启发,法国平面设计师邦卡采用了相同的方法,创作了一系列简约、平面的超级英雄插图。这些插图涵…

自制操作系统日志——第二十二天

自制操作系统日志——第二十二天 今天&#xff0c;我们将继续再完善一下保护操作系统的内容&#xff0c;以及进一步的利用c语言显示字符串&#xff01; 文章目录自制操作系统日志——第二十二天一、保护操作系统3手动强制关闭应用程序二、用c语言显示字符串API 显示窗口总结一…

vivado使用方法(初级)

文章目录1 创建新工程1.1 工程创建1.2 新建Verilog文件1.3 仿真参考1 创建新工程 1.1 工程创建 1、首先打开Vavido软件&#xff0c;点击Creat Project或者在File——>Project——>New里面进行新工程的创建 2、然后在弹出的界面上点击Next进入下一个界面进行项目的命名…

全站最简单 “数据滚动可视化大屏” 【JS基础拿来即用】

源码获取方式&#xff1a; 数据滚动大屏源码&#xff0c;原生js实现超级简单-Javascript文档类资源-CSDN下载原生js实现的数据滚动大屏案例&#xff0c;实现应该是全网最简单的&#xff0c;拿来直接使用即可&#xff0c;没有会员的小伙伴去我文章主更多下载资源、学习资料请访问…

基于Python实现的遗传算法求TSP问题

遗传算法求TSP问题 目录 人工智能第四次实验报告 1 遗传算法求TSP问题 1 一 、问题背景 1 1.1 遗传算法简介 1 1.2 遗传算法基本要素 2 1.3 遗传算法一般步骤 2 二 、程序说明 3 2.3 选择初始群体 4 2.4 适应度函数 4 2.5 遗传操作 4 2.6 迭代过程 4 三 、程序测试 5 3.1 求解…

Vue3+elementplus搭建通用管理系统实例七:通用表格实现上

一、本章内容 使用配置的方式实现表格的界面的自动生成、自动解析实体配置信息,并生成表格列、筛选项等功能,完整课程地址 二、效果预览 三、开发视频

动手实现深度学习(12): 卷积层的实现

9.1 卷积层的运算 传送门: https://www.cnblogs.com/greentomlee/p/12314064.html github: Leezhen2014: https://github.com/Leezhen2014/python_deep_learning 卷积的forward 卷积的计算过程网上的资料已经做够好了,没必要自己再写一遍。只把资料搬运到这里: http://deepl…

【进击的JavaScript|高薪面试必看】JS基础-作用域和闭包

六年代码两茫茫&#xff0c;不思量&#xff0c;自难忘 6年资深前端主管一枚&#xff0c;只分享技术干货&#xff0c;项目实战经验&#xff0c;面试指导 关注博主不迷路~ 本系列文章是博主精心整理的面试热点问题&#xff0c;吸收了大量的技术博客与面试文章&#xff0c;总结多年…

Java毕设项目——网上宠物店管理系统(java+SSM+Maven+Mysql+Jsp)

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM 技术&#xff1a;Jsp JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a…

收银台——Web自动化测试

目录 一&#xff0c;收银台项目的主要功能&#xff1a; 二&#xff0c;Web自动化测试 一&#xff0c;Web自动化测试&#xff0c;设计测试用例 二&#xff0c;编写测试用例代码 三&#xff0c;测试结果&#xff1a; 四&#xff0c;总结&#xff1a; 一&#xff0c;收银台项…