boot项目中定时任务quartz

最近换项目组,发现项目中定时任务使用的是quartz框架,上一篇文章[springboot定时任务]也是使用的quartz,只不过实现方式不同,于是整理下

定时任务常用方法有Quartz,Spring自带的Schedule框架

Quartz基础知识

quartz常用组件:调度器,触发器,作业。

常用类:jobdetail(定时任务。描述job的核心逻辑);trigger(触发器。一个触发器对应一个定时任务,而一个定时任务可以对应多个触发器);schedule(调度器。管理触发器及定时任务的协调工作,一个schedule可以有多个trigger和jobdetail)

quartz提供两种作业存储类型,RAMJobStore和JDBC作业。

RAMJobStore是内存存储。数据访问快,但由于是内存存储。若服务挂掉,运行的定时任务信息就会丢失。

JDBC是数据库存储。通过quartz.properties文件,持久化任务调度信息。若应用挂掉,重启后会继续执行定时任务。

集群模式

Quartz框架

若部署多台服务器,定时任务在某一时刻只能有一个节点执行,则使用持久化任务调度信息方案
quartz默认的集群方案,保证同一时刻相同触发器只能一个节点执行;若节点执行失败,则会分派到另一节点,中途也会自动检查失效的定时调度,若不成功,则其他节点会继续执行。

定时任务在集群环境下默认是多台服务器会同时执行,这时需要结合项目自己程序判断。

quartz定时任务的配置文件中有一属性 org.quartz.jobStore.isClustered=true则为集群方式,自动判断节点状态。

@Schedule注解定时任务

@Schedule注解会定时跑服务。但是若部署多台服务器时,则会导致每台服务器都会执行一次,解决办法1.指定某台服务器执行 2.使用redis锁 3.数据库状态标识记录。但这种方式若是服务器时间一样,并发时数据库标识在查询时未来得及更新,也会导致多台服务器执行定时任务。详情可见[定时任务的时间修改后立即生效​​​​​​​]

分布式多节点多活应用同一定时任务,多节点同时执行配置

pom.xml
<!--定时任务-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId><version>2.7.18</version>
</dependency>
QuartzConfig类
package com.example.demo.config;import com.example.demo.jobs.Test1Job;
import org.quartz.CronTrigger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;import java.util.Objects;/*** @Auther: lr* @Date: 2024/3/28 14:34* @Description:*/
@Configuration
public class QuartzConfig {@Value("${cron.test1}")private String test1Cron;/*** 定时任务的信息载体* 通过FactoryBean来间接创建Job对象,若有多个Job对象,需定义多次方法* 需要重写Factory相关代码,实现spring容器管理jobdetail* @return*/@Bean(name ="test1JobDetailBean" )public JobDetailFactoryBean initTest1JobDetailBean(){JobDetailFactoryBean jobDetailFactoryBean=new JobDetailFactoryBean();jobDetailFactoryBean.setJobClass(Test1Job.class);return jobDetailFactoryBean;}/*** 触发器* 就是Trigger的一个实现类型,其中用于定义周期时间的CronScheduleBuilder* 实际上,CronTrigger是用于管理一个cron表达式的类型* @return*/@Bean(name = "test1CronTriggerBean")public CronTriggerFactoryBean initTest1CronTriggerBean(){CronTriggerFactoryBean cronTriggerFactoryBean=new CronTriggerFactoryBean();JobDetailFactoryBean jobDetailFactoryBean = this.initTest1JobDetailBean();cronTriggerFactoryBean.setJobDetail(Objects.requireNonNull(jobDetailFactoryBean.getObject()));cronTriggerFactoryBean.setCronExpression(test1Cron);return cronTriggerFactoryBean;}/*** 任务调度器* @param customJobFactory 定时任务的信息载体* @param cronTriggerFactoryBeans 触发器* @return*/@Beanpublic SchedulerFactoryBean initSchedulerFactoryBean(CustomJobFactory customJobFactory,CronTriggerFactoryBean[] cronTriggerFactoryBeans){SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();factoryBean.setJobFactory(customJobFactory);CronTrigger[] cronTriggers=new CronTrigger[cronTriggerFactoryBeans.length];for(int i=0;i<cronTriggerFactoryBeans.length;i++){cronTriggers[i]=cronTriggerFactoryBeans[i].getObject();}//注册触发器,一个Scheduler可以注册若干个触发器factoryBean.setTriggers(cronTriggers);//为Scheduler设置Jobdetail的工厂,可以覆盖掉springboot默认提供的工厂,保证jobdetail自动装配有效factoryBean.setJobFactory(customJobFactory);return factoryBean;}}
 Test1Job
package com.example.demo.jobs;import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;import java.text.SimpleDateFormat;
import java.util.Date;/*** @Auther: lr* @Date: 2024/3/28 14:42* @Description:*/
@Slf4j
public class Test1Job implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {//todoSimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-mm-dd HH:mm");String format = simpleDateFormat.format(new Date());log.info("{}开始执行定时任务1: {}",format ,jobExecutionContext.getJobDetail().getKey().getName());}
}
运行结果

可以看到多台机器都会执行到该定时任务

​​​​​​​

分布式多节点多活应用同一定时任务,单节点执行配置

pom.xml
<!--定时任务-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId><version>2.7.18</version>
</dependency>
<!--引入druid数据源-->
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.6</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional>
</dependency>
<!--定时任务-->
quartz.yml
org:quartz:dataSource:myDS:URL: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=Hongkong&useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=truedriver: com.mysql.cj.jdbc.DrivermaxConnections: 5user: rootpassword: 123456connectionProvider:class: com.example.demo.config.QuartzConnectionProviderscheduler:instanceName: ClusterQuartzinstanceId: AUTOrmi:export: falseproxy: falsewrapJobExecutionInUserTransaction: falsejobStore:driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegatetablePrefix: QRTZ_isClustered: trueacquireTriggersWithinLock: truemisfireThreshold: 5000useProperties: truedataSource: myDSthreadPool:class: org.quartz.simpl.SimpleThreadPoolthreadCount: 1threadPriority: 5threadsInheritContextClassLoaderOfInitializingThread: true
数据库表整理

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;
QuartzSingleConfig配置文件
package com.example.demo.config;import com.example.demo.jobs.Test2Job;
import org.quartz.CronTrigger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;import javax.sql.DataSource;
import java.io.IOException;
import java.util.Objects;
import java.util.Properties;/*** @Auther: lr* @Date: 2024/3/28 14:34* @Description:*/
@Configuration
public class QuartzSingleConfig {@Value("${cron.test2}")private String test2Cron;/*** 加载quartz配置*/@Beanpublic Properties quartzProperties() throws IOException {PropertiesFactoryBean propertiesFactoryBean=new PropertiesFactoryBean();propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.yml"));propertiesFactoryBean.afterPropertiesSet();return propertiesFactoryBean.getObject();}/*** 定时任务的信息载体** @return*/@Bean(name = "test2JobDetailBean")public JobDetailFactoryBean initTest2JobDetailBean() {JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();jobDetailFactoryBean.setJobClass(Test2Job.class);jobDetailFactoryBean.setDurability(true);return jobDetailFactoryBean;}/*** 触发器** @return*/@Bean(name = "test2CronTriggerBean")public CronTriggerFactoryBean initTest2CronTriggerBean() {CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();JobDetailFactoryBean jobDetailFactoryBean = this.initTest2JobDetailBean();cronTriggerFactoryBean.setJobDetail(Objects.requireNonNull(jobDetailFactoryBean.getObject()));cronTriggerFactoryBean.setCronExpression(test2Cron);return cronTriggerFactoryBean;}/*** 任务调度器** @param customJobFactory        定时任务的信息载体* @param cronTriggerFactoryBeans 触发器* @return*/@Bean(name = "schedulerFactoryBean")public SchedulerFactoryBean initSchedulerFactoryBean(CustomJobFactory customJobFactory,CronTriggerFactoryBean[] cronTriggerFactoryBeans,@Qualifier("dataSource") DataSource dataSource) throws IOException {SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();//自动覆盖quartz.properties配置的数据源schedulerFactoryBean.setDataSource(dataSource);//设置quartz的配置文件schedulerFactoryBean.setQuartzProperties(quartzProperties());schedulerFactoryBean.setJobFactory(customJobFactory);CronTrigger[] cronTriggers = new CronTrigger[cronTriggerFactoryBeans.length];for (int i = 0; i < cronTriggerFactoryBeans.length; i++) {cronTriggers[i] = cronTriggerFactoryBeans[i].getObject();}schedulerFactoryBean.setTriggers(cronTriggers);// 用于quartz集群,QuartzScheduler 启动时更新己存在的JobschedulerFactoryBean.setOverwriteExistingJobs(true);//延长启动schedulerFactoryBean.setStartupDelay(1);return schedulerFactoryBean;}}
Durid连接池quartz工具类 QuartzConnectionProvider
package com.example.demo.config;import com.alibaba.druid.pool.DruidDataSource;
import lombok.Data;
import org.quartz.SchedulerException;
import org.quartz.utils.ConnectionProvider;import java.sql.Connection;
import java.sql.SQLException;/*** @Auther: lr* @Date: 2024/3/28 17:01* @Description:*/
@Data
public class QuartzConnectionProvider implements ConnectionProvider {/** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** 常量配置,与quartz.properties文件的key保持一致(去掉前缀),同时提供set方法,Quartz框架自动注入值。** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*///JDBC驱动public String driver;//JDBC连接串public String URL;//数据库用户名public String user;//数据库用户密码public String password;//数据库最大连接数public int maxConnection;//数据库SQL查询每次连接返回执行到连接池,以确保它仍然是有效的。public String validationQuery;private boolean validateOnCheckout;private int idleConnectionValidationSeconds;public String maxCachedStatementsPerConnection;private String discardIdleConnectionsSeconds;public static final int DEFAULT_DB_MAX_CONNECTIONS = 10;public static final int DEFAULT_DB_MAX_CACHED_STATEMENTS_PER_CONNECTION = 120;//Druid连接池private DruidDataSource datasource;/** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** 接口实现** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/public Connection getConnection() throws SQLException {return datasource.getConnection();}public void shutdown() throws SQLException {datasource.close();}public void initialize() throws SQLException {if (this.URL == null) {throw new SQLException("DBPool could not be created: DB URL cannot be null");}if (this.driver == null) {throw new SQLException("DBPool driver could not be created: DB driver class name cannot be null!");}if (this.maxConnection < 0) {throw new SQLException("DBPool maxConnectins could not be created: Max connections must be greater than zero!");}datasource = new DruidDataSource();try {datasource.setDriverClassName(this.driver);} catch (Exception e) {try {throw new SchedulerException("Problem setting driver class name on datasource: " + e.getMessage(), e);} catch (SchedulerException e1) {}}datasource.setUrl(this.URL);datasource.setUsername(this.user);datasource.setPassword(this.password);datasource.setMaxActive(this.maxConnection);datasource.setMinIdle(1);datasource.setMaxWait(0);datasource.setMaxPoolPreparedStatementPerConnectionSize(this.DEFAULT_DB_MAX_CACHED_STATEMENTS_PER_CONNECTION);if (this.validationQuery != null) {datasource.setValidationQuery(this.validationQuery);if (!this.validateOnCheckout)datasource.setTestOnReturn(true);elsedatasource.setTestOnBorrow(true);datasource.setValidationQueryTimeout(this.idleConnectionValidationSeconds);}}
}
Test2Job类
package com.example.demo.jobs;import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;import java.text.SimpleDateFormat;
import java.util.Date;/*** @Auther: lr* @Date: 2024/3/29 9:29* @Description:*/
@Slf4j
public class Test2Job implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {//todoSimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm");String format = simpleDateFormat.format(new Date());log.info("{}开始执行定时任务2: {}",format ,jobExecutionContext.getJobDetail().getKey().getName());}}

启动项目后,可以看出数据库中定时任务的表达式已经存储在表中

 如图所示,定时任务的信息存储在表中。

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

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

相关文章

linux开发之设备树

设备树的基本概念 1.什么是设备树?为什么叫设备树呢? 设备树是描述硬件的文本文件&#xff0c;因为语法结构像树一样。所以叫设备树。 2.基本名词解释 <1>DT:Device Tree //设备树 <2>FDT:Flattened Device Tree //开放设备树&#xff0c;起源于0penFirmware(0F…

[论文笔记]Chain-of-Thought Prompting Elicits Reasoning in Large Language Models

引言 今天带来思维链论文 Chain-of-Thought Prompting Elicits Reasoning in Large Language Models的笔记。 作者探索了如何通过生成一系列中间推理步骤的思维链&#xff0c;显著提升大型语言模型在进行复杂推理时的能力。 1 总体介绍 语言模型的规模扩大已被证明能够带来…

力扣239. 滑动窗口最大值

Problem: 239. 滑动窗口最大值 文章目录 题目描述思路复杂度Code 题目描述 思路 1.编写实现优先队列类&#xff1a; 1.1.实现push(int n):将元素n添加到队列尾&#xff0c;同时将n前面大于n的元素删除 1.2.实现int max():将队列头元素取出&#xff08;由于实现了push所以此时队…

Linux基础 (十):Linux 信号的使用

目录 一、信号的基本概念 二、信号处理常见方式概览 三、修改信号的响应方式 – signal() 3.1 简单复习结束前台进程 3.2 改变SIGINT信号的响应方式 3.3 自定义方式改变进程对信号的响应 3.4 进程对信号作出两种响应 四、发送信号 – kill() 五、利用信号解决僵死进程…

2024电激世界脉动-中国汽车品牌全球化制胜手册

来源&#xff1a;奥美Ogilvy&#xff1a; 近期历史回顾&#xff1a; 2024中国宏观经济专题报告-数据要素市场建设 2023-2024年度报告.pdf 2024制药与生化医疗技术产业链白皮书.pdf 从可再生能源到绿氢-中国投资助力埃及能源转型.pdf 2024有机旅行中国行业指引.pdf 2024中国技术…

运营商系统快速上云的实践分享

运营商系统上云的背景 系统上云是数字经济发展的潮流&#xff0c;在数字化转型的浪潮中&#xff0c;上云已经成为推动各行各业创新和效率提升的关键力量。运营商作为服务行业和企业上云的服务商&#xff0c;积极响应国家号召的同时为行业上云打造案例标杆&#xff0c;自身的系统…

常用目标检测预训练模型大小及准确度比较

目标检测是计算机视觉领域中的一项重要任务&#xff0c;旨在检测和定位图像或者视频中的目标对象。当人类观看图像或视频时&#xff0c;我们可以在瞬间识别和定位感兴趣的对象。目标检测的目标是使用计算机复制这种智能。 近年来&#xff0c;目标检测网络的发展日益成熟&#…

四步简单操作:轻松将iCloud照片恢复到相册

随着智能手机的普及&#xff0c;我们的生活中越来越多的照片存储在了云端&#xff0c;其中iCloud提供了便捷的照片备份和存储服务。但有时候&#xff0c;我们可能会不小心删除了在iCloud上的照片&#xff0c;或者想要将iCloud中的照片恢复到手机相册中。 在这篇文章中&#xf…

【数据结构】快速排序(详解)

目录 快速排序 历史&#xff1a; 基本思想&#xff1a; 主框架&#xff1a; 下面解释实现单次排序的几种版本&#xff1a; 1.Hoare版本 2. 挖坑法 3. 前后指针法 快速排序的实现包括递归与非递归&#xff1a; 1. 递归实现&#xff1a;&#xff08;即开头的基本框架&am…

Jenkins安装 :AWS EC2 Linux

1 JDK11 install # 用的yum安装 # 压缩包安装&#xff0c;下载的jdk-11.0.22_linux-x64_bin.tar.gz在EC2解压&#xff0c;配置环境变量&#xff0c;运行jenkins的时候会报错$ yum -y list java-11* Available Packages java-11-amazon-corretto-devel.x86_64 …

动手学深度学习4.6 暂退法-笔记练习(PyTorch)

以下内容为结合李沐老师的课程和教材补充的学习笔记&#xff0c;以及对课后练习的一些思考&#xff0c;自留回顾&#xff0c;也供同学之人交流参考。 本节课程地址&#xff1a;丢弃法_哔哩哔哩_bilibili 本节教材地址&#xff1a;4.6. 暂退法&#xff08;Dropout&#xff09;…

LangChain技术解密:构建大模型应用的全景指南

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

使用目标检测模型YOLO V9 OBB进行旋转目标的检测:训练自己的数据集(基于卫星和无人机的农业大棚数据集)

我看到YOLO V8中&#xff08;ultralytics版本8.2.18&#xff09;集成了YOLO V9&#xff0c;所以直接在YOLO V8 OBB的基础上实现YOLO V9 OBB&#xff0c;训练结果也出来了&#xff0c;但是评估指标比YOLO V8 OBB低一点点&#xff0c;不知道是不是哪里遗漏修改了......如有大神赐…

【Linux学习】进程间通信 (2) —— 信号

下面是有关进程通信中信号的相关介绍&#xff0c;希望对你有所帮助&#xff01; 小海编程心语录-CSDN博客 目录 1. 信号 1.1 概念 1.2 信号的产生 1.3 信号的处理方式 2. 函数 2.1 kill() 函数 2.2 signal()函数 2.3 sigaction()函数 2.4 sigprocmask()函数 …

文盘Rust -- 生命周期问题引发的 static hashmap 锁

100编程书屋_孔夫子旧书网 2021年上半年,撸了个rust cli开发的框架,基本上把交互模式,子命令提示这些cli该有的常用功能做进去了。项目地址:https://github.com/jiashiwen/interactcli-rs。 春节以前看到axum已经0.4.x了,于是想看看能不能用rust做个服务端的框架。 春节…

如何从Android恢复已删除的文件?3 种有效的方式

有时我们可能会错误地删除Android设备上的重要文件。更疯狂的是&#xff0c;Android手机上的文件在一夜之间消失了&#xff0c;我们不知道为什么。我们感到非常遗憾和恼火&#xff0c;但不知道。但是&#xff0c;此时学习如何从Android手机恢复已删除的文件为时已晚&#xff0c…

Excel 取出每组最后一行

Excel的前两列是两层的分组列&#xff0c;后两列是明细 ABCD1CM11112CM12123CM13134CM14145CM25156CM26167BM11218BM12229BM232310AM113111AM323212AM333313AM3434 现在要取出每小组的最后一行&#xff1a; ABCD1CM14142CM26163BM12224BM23235AM11316AM3434 使用 SPL XLL sp…

拼多多商品详情商品标题sku等信息抓取接口API调用步骤演示

接口名称&#xff1a;item_get_app_pro 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,item_search_sho…

两台电脑怎么互传文件?这些方法你值得一试

在日常生活和工作中&#xff0c;我们经常需要在不同电脑之间传输文件&#xff0c;这可能是文档、照片、音乐或其他类型的文件。两台电脑怎么互传文件是非常有用的技能&#xff0c;可以提高工作效率并简化文件共享过程。本文将介绍三种常见的方法&#xff0c;帮助您了解如何在两…

苹果手机怎么看海拔高度?快速掌握使用技巧

手机不仅能满足我们日常的通讯需求&#xff0c;还内置了许多实用的功能&#xff0c;其中包括查看海拔高度。无论是登山、徒步、骑行还是只是好奇地想要了解所在地的海拔高度&#xff0c;苹果手机都能够满足您的需求。苹果手机怎么看海拔高度&#xff1f;在本文中&#xff0c;我…