Quartz定时任务

news2024/11/16 15:51:58

基本介绍

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个、百个、甚至是好几万个Jobs这样复杂的日程序表,Jobs可以做成标准的Java组件或EJBs
Quartz是一个任务日程管理系统,一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统
Quartz用一个小Java库发布文件(.jar文件),这个库文件包含了所有Quartz核心功能,这些功能的主要接口(API)是Scheduler接口,它提供了简单的操作
例如:将任务纳入日程或者从日程中取消,开始、停止、暂停日程进度

(1)完全由Java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制
(2)可以与J2EE与J2SE应用程序相结合也可以单独使用
(3)允许程序开发人员根据时间的间隔来调度作业
(4)实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联
(5)免费使用,并根据Apache 2.0许可

Quartz拥有完善的事件和监听体系,大部分组件都拥有事件,如任务执行前事件、任务执行后事件、触发器触发前事件、触发后事件、调度器开始事件、关闭事件等等,可以注册相应的监听器处理感兴趣的事件。


下载

1.进入官网

http://www.quartz-scheduler.org/
在这里插入图片描述

2.选择版本下载

在这里插入图片描述

3.文件目录说明

在这里插入图片描述


执行流程

在这里插入图片描述
Job为作业的接口,为任务调度的对象;JobDetail用来描述Job的实现类及其他相关的静态信息;Trigger做为作业的定时管理工具,一个Trigger只能对应一个作业实例,而一个作业实例可对应多个触发器;Scheduler做为定时任务容器,是Quartz最上层的东西,它提携了所有触发器和作业,使它们协调工作,每个Scheduler都存有JobDetail和Trigger的注册,一个Scheduler中可以注册多个JobDetail和多个Trigger


核心接口

(1)Job(任务接口,无状态)

开发者实现该接口定义运行任务。表示一个工作,要执行的具体内容。此接口中只有一个方法

public interface Job {
    void execute(JobExecutionContext context) throws JobExecutionException;
}

Job是一个执行任务的简单java类。任务可以是任何java代码
只需实现org.quartz.Job接口,并将需要执行的任务代码写在execute()中即可。当Quartz确定该是作业运行的时候,它将调用作业。Quartz提供了一个机制来建立具有不同粒度的、可重复的调度表,于是,只需创建一个java类,这个类被调用而执行任务

描述
JobExecutionContext类提供了调度上下文的各种信息。Job运行时的信息保存在JobDataMap实例中

(2)StatefulJob(任务接口,有状态)

任务在执行任务过程中,任何对Job Data Map所作的更改都将丢失而且任务下次执行时也无法看到。
StatefulJob在任务的每次执行之后重新存储JobDataMap

Job vs. StatefulJob
JobDataMap在每次执行之后重新持久化到JobStore中。
两个或多个有状态的JobDetail实例不能并发执行

StatefulJob子接口
Job有一个StatefulJob子接口,代表有状态的任务,该接口是一个没有方法的标签接口,其目的是让Quartz知道任务的类型,以便采用不同的执行方案。无状态任务在执行时拥有自己的JobDataMap拷贝,对JobDataMap的更改不会影响下次的执行。而有状态任务共享共享同一个 JobDataMap实例,每次任务执行对JobDataMap所做的更改会保存下来,每次执行任务后都会对后面的执行发生影响。
正因为这个原因,无状态的Job可以并发执行,而有状态的StatefulJob不能并发执行,这意味着如果前次的StatefulJob还没有执行完毕,下一次的任务将阻塞等待,直到前次任务执行完毕。有状态任务比无状态任务需要考虑更多的因素,程序往往拥有更高的复杂度,因此除非必要,应该尽量使用无状态的Job
如果Quartz使用了数据库持久化任务调度信息,无状态的JobDataMap仅会在Scheduler注册任务时保持一次,而有状态任务对应的JobDataMap在每次执行任务后都会进行保存。

Trigger自身也可以拥有一个JobDataMap其关联的Job可以通过JobExecutionContext#getTrigger()
.getJobDataMap()获取Trigger中的JobDataMap。不管是有状态还是无状态的任务,在任务执行期间对Trigger的JobDataMap所做的更改都不会进行持久,也即不会对下次的执行产生影响。


(3)JobDetail(任务描述)

表示一个具体的可执行的调度程序。ob是这个可执行程调度程序所要执行的内容,另外JobDetail还包含了这个任务调度的方案和策略
Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色
通过该类的构造函数可以更具体地了解它的功用:JobDetail(java.lang.String name, java.lang.String group, java.lang.Class jobClass),该构造函数要求指定Job的实现类,以及任务在Scheduler中的组名和Job名称

JobDetail对象由Quartz客户端在Job被加入到scheduler时创建。它包含了Job的各种设置属性以及一个JobDataMap对象,这个对象被用来存储给定Job类实例的状态信息。Scheduler并不保存真正的Job Class,而是通过JobDetail来保存。

注意:给scheduler传入了一个JobDetail实例,而且这个JobDetail实例只是简单提供了类名来引用被执行的Job。每次scheduler执行这个任务时,它就创建这个类的新实例,然后调用该实例的execute()。Job不必担心线程安全性,因为同一时刻仅有一个线程去执行给定Job类的实例,甚至是并发执行同一Job也是如此
(1)Job类必须有一个无参数的构造函数
(2)Job类中定义的成员数据失去意义,因为这些成员数据值在每次执行的时候被“清空”了


(4)JobBuilder:定义、创建JobDetail实例


(5)Trigger(触发器)

代表一个调度参数的配置,什么时候去调

1.SimpleTrigger:简单触发

SimpleTrigger用来触发只需执行一次或者在给定时间触发并且重复N次且每次执行延迟一定时间的任务
如果想让触发器在2020年4月25日,上午11: 23:54秒执行,然后每个隔10秒钟重复执行一次,并且这样重复5次,那么SimpleTrigger就可以满足要求

2.CronTrigger:表达式触发

如果需要像日历那样按日程来触发任务,而不是像SimpleTrigger那样每隔特定的间隔时间触发,CronTriggers通常比SimpleTrigger更有用
使用CronTrigger,可以指定诸如[每个周五中午]、或者[每个工作日的9:30]或者[从每个周一、周三、周五的上午9:00到上午10:00之间每隔五分钟]这样日程安排
来触发,甚至,像SimpleTrigger样,CronTrigger也有一个startTime以指定日程从什么时候开始,也有一个(可选的)endTime以指定何时日程不再继续

Quartz Cron表达式
支持7个域,分别是秒/分/时/日/月/周/年。年是非必须项
Cron表达式用来配置CronTrigger实例。Corn表达式是一个由7个表达式组成的字符串。每个表达式都描述了一个单独的日程细节。这些表达式用空格分隔

注意:cron表达式中不区分大小写
Cron表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感

名称是否必须允许值特殊字符
0-59, - * /
0-59, - * /
0-23, - * /
1-31, - * ? / L W C
1-7 或 SUN-SAT, - * ? / L C #
1-12 或 JAN-DEC, - * /
空 或 1970-2099, - * /

星号(*):可用在所有字段中,表示对应时间域的每一个时刻,例如:在分钟字段时,表示“每分钟”
问号(?):该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于点位符;
减号(-):表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12;
逗号(,):表达一个列表值,如在星期字段中使用“MON,WED,FRI”,则表示星期一,星期三和星期五;
斜杠(/):x/y表达一个等步长序列,x为起始值,y为增量步长值。如在分钟字段中使用0/15,则表示为0,15,30和45秒,而5/15在分钟字段中表示5,20,35,50,你也可以使用*/y,它等同于0/y;
L(每月/星期的最后一天):该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L在日期字段中,表示这个月份的最后一天,如一月的31号,非闰年二月的28号;如果L用在星期中,则表示星期六,等同于7。但是,如果L出现在星期字段里,而且在前面有一个数值X,则表示“这个月的最后X天”,例如:6L表示该月的最后星期五
W(日期):该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一;如果15号是星期二,那结果就是15号星期二。但必须注意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天。W字符串只能指定单一日期,而不能指定日期范围;
LW组合:在日期字段可以组合使用LW,它的意思是当月的最后一个工作日;
井号(#):该字符只能在星期字段中使用,表示当月某个工作日。如6#3表示当月的第三个星期五(6表示星期五,#3表示当前的第三个),而4#5表示当月的第五个星期三,假设当月没有第五个星期三,忽略不触发;
C:该字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天


常用案例

表示式描述
0 0 12 * * ?每天12点运行
0 15 10 ? * *每天10:15运行
0 15 10 * * ?每天10:15运行
0 15 10 * * ? *每天10:15运行
0 15 10 * * ? 2008在2008年的每天10:15运行
0 * 14 * * ?每天14点到15点之间每分钟运行一次,开始于14:00,结束于14:59
0 0/5 14 * * ?每天14点到15点每5分钟运行一次,开始于14:00,结束于14:55
0 0/5 14,18 * * ?每天14点到15点每5分钟运行一次,此外每天18点到19点每5钟也运行一次
0 0-5 14 * * ?每天14:00点到14:05,每分钟运行一次
0 10,44 14 ? 3 WED3月每周三的14:10分到14:44,每分钟运行一次
0 15 10 ? * MON-FRI每周一,二,三,四,五的10:15分运行

(6)TriggerBuilder:定义、创建Trigger实例


(7)Calendar(时间日期包装类)

org.quartz.Calendar和java.util.Calendar不同,它是一些日历特定时间点的集合(可以简单地将org.quartz.Calendar看作java.util.Calendar的集合,代表一个日历时间点)。一个Trigger可以和多个Calendar关联,以便排除或包含某些时间点

假设:安排每周星期一早上10:00执行任务,但是如果碰到法定的节日,任务则不执行,这时就需要在Trigger触发机制的基础上使用 Calendar进行定点排除
针对不同时间段类型,Quartz在org.quartz.impl.calendar包下提供了若干个Calendar 的实现类,如AnnualCalendar、MonthlyCalendar、WeeklyCalendar分别针对每年、每月和每周进行定义


(8)Scheduler(调度器)

代表一个调度容器,一个调度容器中可以注册多个JobDetail和Trigger。当Trigger与JobDetail组合,就可以被Scheduler容器调度了

代表一个Quartz的独立运行容器,Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中拥有各自的组及名称,组及名称是Scheduler查找定位容器中某一对象的依据,Trigger的组及名称必须唯一,JobDetail的组和名称也必须唯一(但可以和Trigger的组和名称相同,因为它们是不同类型的)。Scheduler定义了多个接口方法,允许外部通过组及名称访问和控制容器中Trigger和JobDetail。

Scheduler可以将Trigger绑定到某一JobDetail中,这样当Trigger触发时,对应的Job就被执行。一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。可以通过SchedulerFactory创建一个Scheduler实例。 Scheduler拥有一个SchedulerContext,它类似于ServletContext,保存着Scheduler上下文信息,Job和
Trigger都可以访问SchedulerContext内的信息。SchedulerContext内部通过一个Map,以键值对的方式维护这些上下文数据,SchedulerContext为保存和获取数据提供了多个put()和getXxx()的方法。可以通过Scheduler# getContext()获取对应的SchedulerContext实例
Scheduler接口有两个实现类:StdScheduler(标准默认调度器)、RemoteScheduler(远程调度器)


常用方法

方法描述
shutdown()关闭定时任务调度器
Date scheduleJob(JobDetail jobDetail,Trigger trigger)添加一个定时任务
Date rescheduleJob(String triggerName,String groupName, Trigger newTrigger)修改一个定时任务,主要是更改trigger
boolean deleteJob(String jobName,String jobGroup)删除一个定时任务,同时也会将于该jobDetail关联的trigger一并删除
String[] getJobGroupNames()取得所有的jobDetail组
String[] getJobNames(String groupName)取得某个group下的所有的jobDetail
JobDetail getJobDetail(String jobName,String jobGroup)取得指定的jobDetail
Trigger[] getTriggersOfJob(String jobName,String groupName)取得指定的jobDetail的所有的Trigger
Trigger getTrigger(String triggerName,String triggerGroup)取得指定的Trigger

(9)ThreadPool(线程池)

Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率


基本使用

1.导入依赖

<!-- quartz任务调度 -->
<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz</artifactId>
	<version>2.3.2</version>
</dependency>
<dependency>
	<groupId>com.zaxxer</groupId>
	<artifactId>HikariCP-java7</artifactId>
	<version>2.4.13</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.7.7</version>
</dependency>
<!-- c3p0依赖,已导入 -->
<dependency>
	<groupId>com.mchange</groupId>
	<artifactId>c3p0</artifactId>
	<version>0.9.5.4</version>
</dependency>
<dependency>
	<groupId>com.mchange</groupId>
	<artifactId>mchange-commons-java</artifactId>
	<version>0.2.15</version>
</dependency>

2.创建一个实现Job类的execute(),存放具体的任务

public class HelloJob implements Job {
	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
		// 打印当前的执行时间
		Date date = new Date();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("现在的时间是:" + sf.format(date));
		// 具体的业务逻辑
		System.out.println("Hello Quartz");
	}
}

3.使用SimpleTrigger(简单触发器)、Scheduler(调度器)

public class HelloScheduler {
    public static void main(String[] args) throws SchedulerException {
        //创建一个jobDetail的实例,将该实例与HelloJob Class绑定
        JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
			.withIdentity("myJob")
			.build();
			
        //创建一个Trigger触发器的实例,定义该job立即执行,并且之后每2秒执行一次,一直执行
        SimpleTrigger trigger = TriggerBuilder.newTrigger()
			.withIdentity("myTrigger")
			.startNow().withSchedule(SimpleScheduleBuilder
			.simpleSchedule()
			.withIntervalInSeconds(2)
			.repeatForever())
			.build();
        //创建schedule实例。调度器
        StdSchedulerFactory factory = new StdSchedulerFactory();
        Scheduler scheduler = factory.getScheduler();
        scheduler.start();
        scheduler.scheduleJob(jobDetail,trigger);
    }
}

Spring中使用

1.导入依赖

<!-- spring后需要context-support -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context-support</artifactId>
	<version>4.3.26.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
	<version>1.7.7</version>
</dependency>
<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz</artifactId>
	<version>2.3.0</version>
</dependency>
<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz-jobs</artifactId>
	<version>2.3.0</version>
</dependency> 

2.三种方式

方式一

(1)继承QuartzJobBean,并重写executeInternal(JobExecutionContext context)

//继承QuartzJobBean,并重写executeInternal方法  
public class QuartzTask extends QuartzJobBean {
	private int timeout;
	private static int i = 0;

	// 调度工厂实例化后,经过timeout时间开始执行调度
	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

	@Override
	protected void executeInternal(JobExecutionContext context) 
throws JobExecutionException {
		System.out.println("task running..." + ++i + "进行中...");
	}
}

(2)配置spring-quratz.xml文件
1.任务调用类;2.任务调用方式;3.任务调用工厂

<!-- 1.配置任务类 -->
<bean id="myJobDetail"
	class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
	<!-- 指定job的名称 -->
	<property name="name" value="exampleJob"/>
	<!-- 指定具体的job类 -->
	<property name="quartzClass" value="com.my.pojo.QuartzTask"/>
	<property name="jobDataAsMap">
		<map>
			<entry key="timeout" value="0" />
		</map>
	</property>
	<!-- 指定job的分组 -->
	<property name="group" value="jobs" />
	<!-- 必须设置为true,如果为false,当没有活动的触发器与之关联时会在调度器中删除该任务 -->
	<property name="durability" value="true" />
	<!-- 指定spring容器的key,如果不设定在job中的jobmap中是获取不到spring容器的 -->
	<property name="applicationContextJobDataKey" value="applicationContext" />
</bean>
	
<!-- 2.调度触发器方式 -->
<bean id="cronTriggerBean"
		class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
	
	<property name="jobDetail">
		<ref bean="myJobDetail" />
	</property>
	<!-- cron表达式 -->
	<!-- 每一分钟执行一次 -->
	<property name="cronExpression" value="0 */1 * * * ?" />
</bean>
	
<!-- 一个job可以有多个trigger -->
<bean id="cronTriggerBeanTwo"
	class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
	<property name="jobDetail" ref="myJobDetailTwo" />
	<property name="cronExpression" value="0 */1 * * * ?" />
</bean>
	
<!-- 3.调度工厂 -->
<bean id="SpringJobSchedulerFactoryBean"
	class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
	<property name="triggers">
		<list>
			<ref bean="cronTriggerBean" />
			<ref bean="cronTriggerBeanTwo" />
		</list>
	</property>
</bean>

方式二

(1)不需要继承基类,仍然是POJO

public class QuartzJob {  
    public void work(){  
        System.out.println("work running...");
    }
}

(2)在spring-quratz.xml配置文件中,配置包装类

<!-- 1.包装工作类 -->
<bean id="quartzJob" class="spring.demo.pojo.QuartzJob"></bean>

<!-- 2.调度触发器方式 -->
<bean id="jobTask"
	class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
	<!-- 需要包装的类,即调度类 -->
	<property name="targetObject">
		<ref bean="quartzJob" />
	</property>
	<!-- 调用类中的方法 -->
	<property name="targetMethod">
		<!-- 具体的方法 -->
		<value>work</value>
	</property>
</bean>

<!-- 3.调度触发器方式 -->
<bean id="cronTriggerBean"
	class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
	<property name="jobDetail">
		<ref bean="jobTask" />
	</property>
	<!-- cron表达式 -->
	<property name="cronExpression">
		<value>10,15,20,25,30,35,40,45,50,55 * * * * ?</value>
	</property>
</bean>

<!-- 4.调度工厂 -->
<bean id="SpringJobSchedulerFactoryBean"
	class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
	<property name="triggers">
		<list>
			<ref bean="cronTriggerBean" />
		</list>
	</property>
</bean>

方式三

(1)配置applicationContext.xml
通过@Scheduled注解的方式实现,需要修改applicationContext.xml三个部分内容
applicationContext.xml中添加task命名空间,然后添加如下代码

<task:annotation-driven/>

(2)使用@Scheduled注解
最后在定时任务上添加上@Scheduled注解即可,一般都采用cronTrigger方式,即@Scheduled(cron=“相应的定时表达式”)

@Service
public class QuartzService {
	@Scheduled(cron = "0/2 * * * * *")
	public void process() {
		System.out.println("job run...");
	}

	public static void main(String[] args) throws InterruptedException {
		ClassPathXmlApplicationContext context = 
new ClassPathXmlApplicationContext("applicationContext.xml");
		while (true) {
			System.out.println("main running..." + context);
			Thread.sleep(10000);
		}
	}
}

Spring Boot整合Quartz任务调度

1.导入依赖

<!--spring boot集成quartz -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

2.实现QuartzJobBean,提供具体任务(DateTimeJob.java,具体的业务逻辑代码)

public class DateTimeJob extends QuartzJobBean {
	@Override
	protected void executeInternal(JobExecutionContext jobExecutionContext) 
throws JobExecutionException {
		// 获取JobDetail中关联的数据
		String msg = (String) jobExecutionContext.getJobDetail()
.getJobDataMap()
.get("msg");
		System.out.println("current time :" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "---" + msg);
	}
}

3.@Configuration配置类(QuartzConfig.java,配置触发器、调度器)

@Configuration
public class QuartzConfig {
	
	// 任务描述,具体可执行的程序
	@Bean
	public JobDetail printTimeJobDetail() {
		return JobBuilder.newJob(DateTimeJob.class) // PrintTimeJob业务类
				.withIdentity("DateTimeJob") // 可以给该JobDetail起一个id
				// 每个JobDetail内都有一个Map,包含了关联到这个Job的数据,在Job类中可以通过context获取
				.usingJobData("msg", "Hello Quartz") // 关联键值对
				.storeDurably() // 即使没有Trigger关联时,也不需要删除该JobDetail
				.build();
	}

    // 触发器关联调度器
	@Bean
	public Trigger printTimeJobTrigger() {
		// 表达式调度器
		CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder
.cronSchedule("0/1 * * * * ?");
		return TriggerBuilder.newTrigger()
						.forJob(printTimeJobDetail()) // 关联上述的JobDetail
						.withSchedule(cronScheduleBuilder) // 关联触发器
						.withIdentity("quartzTaskService") // 给Trigger(触发器)起个名字
						.build();
	}
}

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

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

相关文章

android framework-ActivityManagerService(AMS)下

一、ActivityThread \frameworks\base\core\java\android\app\ActivityThread.java 1.1、main public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");// Install selective syscall interceptionAnd…

java native 方法编写

目录 前言 1、创建 java native 方法 2、创建洞态链接库项目 3、加载 dll 文件 前言 Java 提供了调用 C 或 C 函数的方法&#xff0c;这种方法就是 native 方法&#xff0c;全称 Java Native Interface (JNI) 1、创建 java native 方法 1&#xff09;新建 java 类文件 …

【CMake】如何使用CMake构建一个工程

1.如何使用CMake构建一个工程 1. 使用 CMakelists.txt 构建工程 一个最简单 CMake 的项目是将某个源文件构建成为可执行文件&#xff0c;使用CMake 构建项目时&#xff0c;你需要创建一个 CMakeLists.txt 文件&#xff0c;通常情况下&#xff0c;下面三条命令在每个 CMakeLis…

四结4.20

这俩天实现了分离客服端和服务端&#xff0c; 先将对象序列化&#xff0c;通过socket从客户端发送到服务端&#xff0c;反序列化 进行数据库操作&#xff0c;最后向客户端返回结果&#xff0c;渲染javafx的画面 中途遇到俩种异常&#xff0c;因为一报错弹出一大段红色的英语…

力扣sql中等篇练习(九)

力扣sql中等篇练习(九) 1 电影评分 1.1 题目内容 1.1.1 基本题目信息1 1.1.2 基本题目信息2 1.1.3 示例输入输出 a 示例输入 b 示例输出 1.2 示例sql语句 # 只要一个 可以考虑order by加上 limit的组SELECT子句中子查询的结果 # 电影名称和姓名不可能重复,所以直接Union a…

【RecyclerView】同时刷新和滚动导致,滚动位置异常(一)

前置&#xff1a; 被选中item高度与非选中item高度不一致&#xff0c;且硬件有点卡&#xff0c;运行会有一定卡顿。 可视界面的item为三个&#xff0c;总数据为十个。 期望效果&#xff1a; 》 实际上效果&#xff1a; 代码&#xff1a; mListAdapter.setSelectedPosition(…

学成在线笔记+踩坑(6)——【媒资模块】视频处理。FFmpeg+XXL-JOB

导航&#xff1a; 【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线牛客面试题 目录 1 视频转码需求 1.1 视频编码格式和文件格式 1.2 windows使用编码工具FFmpeg 1.3 视频处理工具类 1.3.1 拼装FFmpeg命令的各工具类 1…

复旦MOSS大模型开源了「中国版ChatGPT」,Github和Hugging Face同时上线

最近&#xff0c;ChatGPT非常火&#xff0c;从ChatGPT3到ChatGPT4&#xff0c;都非常火。无论是否为互联网行业的&#xff0c;多少都听到过关于ChatGPT的消息。虽然百度、阿里等互联网巨头都已经宣布将会推出相关的类ChatGPT产品。但目前还未有成型的产品上线。 而昨日&#x…

94. 二叉树的中序遍历【119】

难度等级&#xff1a;容易 上一篇算法&#xff1a; 102. 二叉树的层序遍历【206】 力扣此题地址&#xff1a; 94. 二叉树的中序遍历 - 力扣&#xff08;Leetcode&#xff09; 1.题目&#xff1a;94. 二叉树的中序遍历 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序…

AlgoC++第四课:逻辑回归

目录 逻辑回归前言1. 鸢尾花分类问题1.1 基于线性回归的思考1.2 损失函数 2. 伯努利分布3. 示例代码3.1 数据可视化3.2 日志信息打印3.3 数据读取和处理3.4 逻辑回归模型3.5 完整示例代码3.6 python实现 4. 思考总结 逻辑回归 前言 手写AI推出的全新面向AI算法的C课程 Algo C&…

InnoDB中必须要了解的几个关键特性

InnoDB引擎在设计中使用了很多技术思想。下面我们主要介绍一些InnoDB的关键特性&#xff0c;帮助你去更好了解 InnoDB。 关键特性 1.预读&#xff08;1&#xff09;预读的两种算法&#xff08;2&#xff09;在InnoDB中相关配置 2.插入缓冲2.1 Insert Buffer2.2 Change Buffer2…

跨域的五种最常见解决方案

这是一篇笔记 什么是跨域&#xff1f; 跨域不是问题&#xff0c;是一种安全机制。浏览器有一种策略名为同源策略&#xff0c;同源策略规定了部分请求不能被浏览器所接受。 值得一提的是&#xff1a;同源策略导致的跨域是浏览器单方面拒绝响应数据&#xff0c;服务器端是处理…

C#基于asp.net的企业人事管理系统的研究与实现

&#xff08;一&#xff09;任务 1.本课题的任务是对人事管理系统的管理过程进行分析&#xff0c;列出逻辑实现过程&#xff0c;对系统进行逻辑设计和数据库设计&#xff1b; 2.主要实现系统管理、档案管理、考勤管理、薪水管理等功能&#xff1b; 3.实现企业员工的相关信息&am…

一篇文章教你解决node-sass 4.12.0 安装失败,一劳永逸

已知&#xff1a; 使用mac电脑使用的node版本是v14.20.0 问题&#xff1a;在安装node-sass 4.12.0的时候报错如下 看到这一堆错误&#xff0c;千万不要立马复制粘贴到浏览器去搜&#xff0c;感觉像无头苍蝇乱撞&#xff0c;好歹稍微看一下什么意思。 显而易见是有一个文档40…

浅析低代码开发的典型应用构建场景v

在数字经济蓬勃发展的大势之下&#xff0c;企业软件开发人员供给不足、开发速度慢、开发成本高、数字化和智能化成效不明显等问题日益凸出&#xff0c;阻碍了企业的数字化转型。 而近年来&#xff0c;低代码的出现推动了经济社会的全面提效&#xff0c;也成为人才供求矛盾的润…

【Docker】限制已运行容器的Cpu和内存

docker限制已运行容器的Cpu和内存 本文首发于 慕雪的寒舍 1.问题描述 最近云服务器的内存经常不够用&#xff0c;而且是莫名其妙的增多&#xff0c;在腾讯云的控制台里面看&#xff0c;4g的内存占用了3.2g&#xff0c;就卡到连ssh都连不上了 PS: 已换过网络和设备&#xff0c…

只要10分钟,零代码基础搞定炫酷大屏设计(内附详细教程)

近几年可视化大屏再次被推上热搜&#xff0c;无论是已经结束的疫情时代指挥中心大屏&#xff0c;还是每年购物节的大屏数据成交额&#xff0c;或者是日常会议中的大屏分析&#xff0c;到处都是可视化大屏的身影。 有人会说&#xff0c;这种大屏一定需要大量的财力、技术顶端的…

开源构建系统Buck2发布

看来最近 Meta 的工程师是一点都没有闲着&#xff0c;前两天刚开源 AI 图像分割模型&#xff0c;这不就又发布了名为 Buck2 的开源构建系统。 Buck2 是一个已经在 Meta 内部使用了一段时间的大型构建系统&#xff0c;目前 Meta 有数千名开发人员正在使用该构建系统&#xff0c;…

IP地址配置

1.vi /etc/sysconfig/network-scripts/ifcfg-ens33 &#xff08;在配置文件中修改&#xff09; 配置文件内容为&#xff1a; IPADDR:配置IP地址 NETMASK:配置子网掩码 GATEWAY:配置网关 DNS:配置dns地址 BOOTPROTO&#xff1a;设置获取ip的方式\DHCP为动态获取\ static为…

C++(GCC)生成和使用静态库

C&#xff08;GCC&#xff09;生成和使用静态库 文章目录 C&#xff08;GCC&#xff09;生成和使用静态库1、前言1.1 什么是静态库1.2 静态库优缺点1.3 C使用静态库的方法1.4 注意事项 2、linux下C生成静态库.a3、链接使用静态库 更多精彩内容&#x1f449;个人内容分类汇总 &a…