Quartz认知篇 - 初识分布式任务调度Quartz

news2024/11/29 22:41:56

定时任务的使用场景

在遇到如下几种场景可以考虑使用定时任务来解决:

  • 某个时刻或者时间间隔执行任务
  • 批量数据进行处理
  • 对两个动作进行解耦

Quartz

介绍

Quartz 是一个特性丰富的、开源的任务调度库,几乎可以嵌入所有的 Java 程序,包括很小的独立应用程序到大型商业系统。Quartz 可以用来创建成百上千的简单的或者复杂的任务,并且这些任务可以作为执行任何事情的标准 Java 组件。Quartz 拥有很多企业级别的特性,包括支持 JTA 事务和集群。

Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, such as support for JTA transactions and clustering.

体系结构

在这里插入图片描述

配置触发的规则

定义要执行的任务,代码/脚本

集中管理配置

并发执行任务,互不干扰

调度器控制任务的生命周期

可以集成 Spring、Spring Boot

任务

可以实现 Job 接口来定义一个任务,然后重写它的 execute 方法来定义任务执行的逻辑。

public class MyJob implements Job {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyJob.class);

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        LOGGER.info(simpleDateFormat.format(new Date()) + ", 任务1执行了, " + jobDataMap.getString("hello"));
    }
}

而调度器的调度方法需要指定一个 JobDetail,即任务明细。JobDetail 可以通过 JobBuilder 的相关方法进行实例化。

JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
        .withIdentity("myJob", "my-job-group")
        .usingJobData("hello", "tom")
        .usingJobData("hi", "selina")
        .build();

接下来,看下 JobBuilder 中定义的一些比较重要的方法。

1、newJob 方法

实例化 JobBuilder(可以指定一个任务)

public static JobBuilder newJob() {
  return new JobBuilder();
}

public static JobBuilder newJob(Class<? extends Job> jobClass) {
  JobBuilder b = new JobBuilder();
  b.ofType(jobClass);
  return b;
}

2、ofType 方法

指定任务

public JobBuilder ofType(Class<? extends Job> jobClazz) {
  this.jobClass = jobClazz;
  return this;
}

3、withIdentity 方法

指定任务的名字和组

public JobBuilder withIdentity(String name) {
  key = new JobKey(name, null);
  return this;
}

public JobBuilder withIdentity(String name, String group) {
  key = new JobKey(name, group);
  return this;
}

public JobBuilder withIdentity(JobKey jobKey) {
  this.key = jobKey;
  return this;
}

4、withDescription 方法

指定任务的描述

public JobBuilder withDescription(String description) {
  this.description = description;
  return this;
}

5、requestRecovery 方法

指定任务遇到“recovery”或者“fail-over”情形是否应该重新执行

public JobBuilder requestRecovery() {
  this.shouldRecover = true;
  return this;
}

public JobBuilder requestRecovery(boolean jobShouldRecover) {
  this.shouldRecover = jobShouldRecover;
  return this;
}

6、storeDurably 方法

指定任务是否应该持久化

public JobBuilder storeDurably() {
  this.durability = true;
  return this;
}

public JobBuilder storeDurably(boolean jobDurability) {
  this.durability = jobDurability;
  return this;
} 

7、usingJobData 方法

添加一组键值对到 JobDetail 的 JobDataMap 属性中

public JobBuilder usingJobData(String dataKey, String value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public JobBuilder usingJobData(String dataKey, Integer value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public JobBuilder usingJobData(String dataKey, Long value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public JobBuilder usingJobData(String dataKey, Float value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public JobBuilder usingJobData(String dataKey, Double value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public JobBuilder usingJobData(String dataKey, Boolean value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public JobBuilder usingJobData(JobDataMap newJobDataMap) {
  jobDataMap.putAll(newJobDataMap);
  return this;
}

8、setJobData 方法

覆盖 JobDetail 的 JobDataMap 属性

public JobBuilder setJobData(JobDataMap newJobDataMap) {
  jobDataMap = newJobDataMap;
  return this;
}

9、build 方法

构建 JobDetailImpl 实例

public JobDetail build() {

    JobDetailImpl job = new JobDetailImpl();
    
    job.setJobClass(jobClass);
    job.setDescription(description);
    if(key == null)
        key = new JobKey(Key.createUniqueName(null), null);
    job.setKey(key); 
    job.setDurability(durability);
    job.setRequestsRecovery(shouldRecover);
    
    
    if(!jobDataMap.isEmpty())
        job.setJobDataMap(jobDataMap);
    
    return job;
}

触发器

任务触发的规则。

调度器的调度方法需要指定一个 Trigger 实例,即触发器。可以通过 TriggerBuilder 的相关方法构建一个 Trigger 实例。

Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("myTrigger", "my-trigger-group")
        .startNow()
        .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(5)
                .repeatForever())
        .build();

接下来看下 TriggerBuilder 定义的一些比较重要的方法。

1、newTrigger 方法

构建 TriggerBuilder 实例

public static TriggerBuilder<Trigger> newTrigger() {
  return new TriggerBuilder<Trigger>();
}

2、withIdentity 方法

设置触发器的名字和组名

public TriggerBuilder<T> withIdentity(String name) {
  key = new TriggerKey(name, null);
  return this;
}

public TriggerBuilder<T> withIdentity(String name, String group) {
  key = new TriggerKey(name, group);
  return this;
}

public TriggerBuilder<T> withIdentity(TriggerKey triggerKey) {
  this.key = triggerKey;
  return this;
}

3、withDescription 方法

设置触发器的描述

public TriggerBuilder<T> withDescription(String triggerDescription) {
  this.description = triggerDescription;
  return this;
}

4、withPriority 方法

设置触发器的优先级(如果有多个启动时间相同的触发器,根据触发器的优先级由大到小的顺序进行启动)

public TriggerBuilder<T> withPriority(int triggerPriority) {
  this.priority = triggerPriority;
  return this;
}

5、modifiedByCalendar 方法

设置应用到该触发器调度的 Calendar 的名字

public TriggerBuilder<T> modifiedByCalendar(String calName) {
  this.calendarName = calName;
  return this;
}

6、startAt 方法

设置触发器的开始时间

public TriggerBuilder<T> startAt(Date triggerStartTime) {
  this.startTime = triggerStartTime;
  return this;
}

7、startNow 方法

设置触发器立即开始

public TriggerBuilder<T> startNow() {
  this.startTime = new Date();
  return this;
}

8、endAt 方法

设置触发器的结束时间

public TriggerBuilder<T> endAt(Date triggerEndTime) {
  this.endTime = triggerEndTime;
  return this;
}

9、withSchedule 方法

设置用于触发器调度的 ScheduleBuilder

public <SBT extends T> TriggerBuilder<SBT> withSchedule(ScheduleBuilder<SBT> scheduleBuilder) {
  this.scheduleBuilder = scheduleBuilder;
  returnt (TriggerBuilder<SBT>) this;
}

10、forJob 方法

设置触发器关联的任务

public TriggerBuilder<T> forJob(JobKey jobKey) {
  this.jobKey = jobKey;
  return this;
}

public TriggerBuilder<T> forJob(String jobName) {
  this.jobKey = new JobKey(jobName, null);
  retun this;
}

public TriggerBuilder<T> forJob(String jobName, String jobGroup) {
  this.jobKey = new JobKey(jobName, jobGroup);
  return this;
}

public TriggerBuilder<T> forJob(JobDetail jobDetail) {
  JobKey k = jobDetail.getKey();
  if (k.getName() == null) {
    throw new IllegalArgumentException("The given job has not yet had a name assigned to it.");
  }
  this.jobKey = k;
  return this;
}

11、usingJobData 方法

添加一组键值对到触发器的 JobDataMap 属性中

public TriggerBuilder<T> usingJobData(String dataKey, String value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(String dataKey, String value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(String dataKey, Integer value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(String dataKey, Long value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(String dataKey, Float value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(String dataKey, Double value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(String dataKey, Boolean value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(JobDataMap newJobDataMap) {
  for(String dataKey: jobDataMap.keySet()) {
    newJobDataMap.put(dataKey, jobDataMap.get(dataKey));
  }
  jobDataMap = newJobDataMap; 
  return this;
}

12、build 方法

构建具体的 Trigger 实例

public T build() {

    if(scheduleBuilder == null)
        scheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
    MutableTrigger trig = scheduleBuilder.build();
    
    trig.setCalendarName(calendarName);
    trig.setDescription(description);
    trig.setStartTime(startTime);
    trig.setEndTime(endTime);
    if(key == null)
        key = new TriggerKey(Key.createUniqueName(null), null);
    trig.setKey(key); 
    if(jobKey != null)
        trig.setJobKey(jobKey);
    trig.setPriority(priority);
    
    if(!jobDataMap.isEmpty())
        trig.setJobDataMap(jobDataMap);
    
    return (T) trig;
}

SimpleTrigger

时间间隔执行n次(时分秒)

1、simpleSchedule 方法

构建 SimpleScheduleBuilder 实例

public static SimpleScheduleBuilder simpleSchedule() {
    return new SimpleScheduleBuilder();
}

2、repeat…Forever 方法

指定时间间隔,永久重复执行

// 指定每隔一分钟永久重复执行
public static SimpleScheduleBuilder repeatMinutelyForever() {
    return simpleSchedule()
        .withIntervalInMinutes(1)
        .repeatForever();
}

// 指定每隔多少分钟永久重复执行
public static SimpleScheduleBuilder repeatMinutelyForever(int minutes) {
    return simpleSchedule()
        .withIntervalInMinutes(minutes)
        .repeatForever();
}

// 指定每隔一秒永久重复执行
public static SimpleScheduleBuilder repeatSecondlyForever() {
    return simpleSchedule()
        .withIntervalInSeconds(1)
        .repeatForever();
}

// 指定每隔多少秒永久重复执行
public static SimpleScheduleBuilder repeatSecondlyForever(int seconds) {
    return simpleSchedule()
        .withIntervalInSeconds(seconds)
        .repeatForever();
}

// 指定每隔一小时永久重复执行
public static SimpleScheduleBuilder repeatHourlyForever() {
    return simpleSchedule()
        .withIntervalInHours(1)
        .repeatForever();
}

// 指定每隔多少小时永久重复执行
public static SimpleScheduleBuilder repeatHourlyForever(int hours) {
    return simpleSchedule()
        .withIntervalInHours(hours)
        .repeatForever();
}

3、repeat…ForTotalCount 方法

指定时间间隔,重复执行直到指定次数

// 每隔一分钟重复执行一次,直到指定次数
public static SimpleScheduleBuilder repeatMinutelyForTotalCount(int count) {
    if(count < 1)
        throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count);
    return simpleSchedule()
        .withIntervalInMinutes(1)
        .withRepeatCount(count - 1);
}

// 每隔多少分钟重复执行一次,直到指定次数
public static SimpleScheduleBuilder repeatMinutelyForTotalCount(int count, int minutes) {
    if(count < 1)
        throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count);
    return simpleSchedule()
        .withIntervalInMinutes(minutes)
        .withRepeatCount(count - 1);
}

// 每隔一秒重复执行一次,直到指定次数
public static SimpleScheduleBuilder repeatSecondlyForTotalCount(int count) {
    if(count < 1)
        throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count);
    return simpleSchedule()
        .withIntervalInSeconds(1)
        .withRepeatCount(count - 1);
}

// 每隔多少秒重复执行一次,直到指定次数
public static SimpleScheduleBuilder repeatSecondlyForTotalCount(int count, int seconds) {
    if(count < 1)
        throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count);
    return simpleSchedule()
        .withIntervalInSeconds(seconds)
        .withRepeatCount(count - 1);
}

// 每隔一小时重复执行一次,直到指定次数
public static SimpleScheduleBuilder repeatHourlyForTotalCount(int count) {
    if(count < 1)
        throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count);
    return simpleSchedule()
        .withIntervalInHours(1)
        .withRepeatCount(count - 1);
}

// 每隔多少小时重复执行一次,直到指定次数
public static SimpleScheduleBuilder repeatHourlyForTotalCount(int count, int hours) {
    if(count < 1)
        throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count);
    return simpleSchedule()
        .withIntervalInHours(hours)
        .withRepeatCount(count - 1);
}

4、withInterval… 方法

指定时间间隔,执行一次

// 每隔多少毫秒执行一次
public SimpleScheduleBuilder withIntervalInMilliseconds(long intervalInMillis) {
    this.interval = intervalInMillis;
    return this;
}

// 每隔多少秒执行一次
public SimpleScheduleBuilder withIntervalInSeconds(int intervalInSeconds) {
    this.interval = intervalInSeconds * 1000L;
    return this;
}

// 每隔多少分钟执行一次
public SimpleScheduleBuilder withIntervalInMinutes(int intervalInMinutes) {
    this.interval = intervalInMinutes * DateBuilder.MILLISECONDS_IN_MINUTE;
    return this;
}

// 每隔多少小时执行一次
public SimpleScheduleBuilder withIntervalInHours(int intervalInHours) {
    this.interval = intervalInHours * DateBuilder.MILLISECONDS_IN_HOUR;
    return this;
}

5、withRepeatCount 方法

指定重复执行的次数

public SimpleScheduleBuilder withRepeatCount(int triggerRepeatCount) {
    this.repeatCount = triggerRepeatCount;
    return this;
}

6、repeatForever 方法

指定永久重复执行

public SimpleScheduleBuilder repeatForever() {
    this.repeatCount = SimpleTrigger.REPEAT_INDEFINITELY;
    return this;
}

7、withMisfire 方法

设置触发器错过启动时间的补偿策略

public SimpleScheduleBuilder withMisfireHandlingInstructionIgnoreMisfires() {
    misfireInstruction = Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY;
    return this;
}

public SimpleScheduleBuilder withMisfireHandlingInstructionFireNow() {
    misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW;
    return this;
}

public SimpleScheduleBuilder withMisfireHandlingInstructionNextWithExistingCount() {
    misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT;
    return this;
}

public SimpleScheduleBuilder withMisfireHandlingInstructionNextWithRemainingCount() {
    misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT;
    return this;
}

public SimpleScheduleBuilder withMisfireHandlingInstructionNowWithExistingCount() {
    misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT;
    return this;
}

public SimpleScheduleBuilder withMisfireHandlingInstructionNowWithRemainingCount() {
    misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT;
    return this;
}

CalendarIntervalTrigger

时间间隔执行一次(年月周日时分秒)

1、calendarIntervalSchedule 方法

构建 CalendarIntervalScheduleBuilder 实例

public static CalendarIntervalScheduleBuilder calendarIntervalSchedule() {
  return new CalendarIntervalScheduleBuilder();
}

2、withInterval…方法

每隔多少时间间隔执行一次

// 每隔多少时间单位执行一次
public CalendarIntervalScheduleBuilder withInterval(int timeInterval, IntervalUnit unit) {
    if(unit == null)
        throw new IllegalArgumentException("TimeUnit must be specified.");
    validateInterval(timeInterval);
    this.interval = timeInterval;
    this.intervalUnit = unit;
    return this;
}

// 每隔多少秒执行一次
public CalendarIntervalScheduleBuilder withIntervalInSeconds(int intervalInSeconds) {
    validateInterval(intervalInSeconds);
    this.interval = intervalInSeconds;
    this.intervalUnit = IntervalUnit.SECOND;
    return this;
}

// 每隔多少分钟执行一次
public CalendarIntervalScheduleBuilder withIntervalInMinutes(int intervalInMinutes) {
    validateInterval(intervalInMinutes);
    this.interval = intervalInMinutes;
    this.intervalUnit = IntervalUnit.MINUTE;
    return this;
}

// 每隔多少小时执行一次
public CalendarIntervalScheduleBuilder withIntervalInHours(int intervalInHours) {
    validateInterval(intervalInHours);
    this.interval = intervalInHours;
    this.intervalUnit = IntervalUnit.HOUR;
    return this;
}

// 每隔多少天执行一次
public CalendarIntervalScheduleBuilder withIntervalInDays(int intervalInDays) {
    validateInterval(intervalInDays);
    this.interval = intervalInDays;
    this.intervalUnit = IntervalUnit.DAY;
    return this;
}

// 每隔多少周执行一次
public CalendarIntervalScheduleBuilder withIntervalInWeeks(int intervalInWeeks) {
    validateInterval(intervalInWeeks);
    this.interval = intervalInWeeks;
    this.intervalUnit = IntervalUnit.WEEK;
    return this;
}

// 每隔多少月执行一次
public CalendarIntervalScheduleBuilder withIntervalInMonths(int intervalInMonths) {
    validateInterval(intervalInMonths);
    this.interval = intervalInMonths;
    this.intervalUnit = IntervalUnit.MONTH;
    return this;
}

// 每隔多少年执行一次
public CalendarIntervalScheduleBuilder withIntervalInYears(int intervalInYears) {
    validateInterval(intervalInYears);
    this.interval = intervalInYears;
    this.intervalUnit = IntervalUnit.YEAR;
    return this;
}

3、withMisfire… 方法

设置触发器错过启动时间的补偿策略

public CalendarIntervalScheduleBuilder withMisfireHandlingInstructionIgnoreMisfires() {
    misfireInstruction = Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY;
    return this;
}

public CalendarIntervalScheduleBuilder withMisfireHandlingInstructionDoNothing() {
    misfireInstruction = CalendarIntervalTrigger.MISFIRE_INSTRUCTION_DO_NOTHING;
    return this;
}

public CalendarIntervalScheduleBuilder withMisfireHandlingInstructionFireAndProceed() {
    misfireInstruction = CalendarIntervalTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW;
    return this;
}

4、inTimeZone 方法

设置时区

public CalendarIntervalScheduleBuilder inTimeZone(TimeZone timezone) {
    this.timeZone = timezone;
    return this;
}

5、build 方法

构建 CalendarIntervalTriggerImpl 实例

@Override
public MutableTrigger build() {
    CalendarIntervalTriggerImpl st = new CalendarIntervalTriggerImpl();
    st.setRepeatInterval(interval);
    st.setRepeatIntervalUnit(intervalUnit);
    st.setMisfireInstruction(misfireInstruction);
    st.setTimeZone(timeZone);
    st.setPreserveHourOfDayAcrossDaylightSavings(preserveHourOfDayAcrossDaylightSavings);
    st.setSkipDayIfHourDoesNotExist(skipDayIfHourDoesNotExist);
    return st;
}

DailyTimeIntervalTrigger

CronTrigger

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

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

相关文章

基于二叉树的改进SPIHT算法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

电脑怎么设置动态壁纸?关于Windows和Mac壁纸的设置方法

为了让电脑桌面更加美观舒适&#xff0c;很多人都会给电脑的桌面设置自己喜欢的壁纸。图片壁纸很多人都会设置&#xff0c;但是电脑怎么设置动态壁纸&#xff1f;这是很多人的困扰。其实方法同样很简单&#xff0c;下面有关于Windows和Mac动态壁纸的设置方法&#xff0c;一起来…

【阶段四】Python深度学习03篇:深度学习基础知识:神经网络可调超参数:激活函数、损失函数与评估指标

本篇的思维导图: 神经网络可调超参数:激活函数 神经网络中的激活函数(有时也叫激励函数)。 在逻辑回归中,输入的特征通过加权、求和后,还将通过一个Sigmoid逻辑函数将线性回归值压缩至[0,1]区间,以体现分类概率值。这个逻辑函数在神经网络中被称为…

PyCharm调用远程Python解释器

PyCharm调用远程Python解释器 PyCharm中直接调用远程服务器中Python解释器&#xff1a; 本地不用搭建Python环境。既避免了本地使用Window而服务器使用Linux系统不统一情况&#xff0c;又不用担心本地调试没问题而放到服务器上就出现问题。 PyCharm中打开项目并设置Python解释…

封装chrome镜像

chrome镜像 selenium提供了一个镜像&#xff0c;但这个镜像里面包含了比较多的东西&#xff1a; 镜像地址-github supervisord java chrome webDriver 实际的使用中遇到了一些问题 chrome遇到一些比较耗费内存和cup的操作的时候&#xff0c;有的时候会kill掉java进程&a…

干货 | 大数据交易所数据安全流通体系标准化尝试

以下内容整理自清华大学《数智安全与标准化》课程大作业期末报告同学的汇报内容。第一部分&#xff1a;国内大数据交易所发展现状第二部分&#xff1a;国外大数据交易模式及法律法规欧盟的数据交易模式是基于2022年5月16日所提出的《数据治理法案》&#xff0c;其中提出了数据中…

【C++11】—— 包装器

目录 一、function包装器 1. function包装器基本介绍 2. function包装器统一类型 3. function包装器的使用场景 二、bind包装器 一、function包装器 1. function包装器基本介绍 function包装器 也叫作适配器。C中的function本质是一个类模板&#xff0c;也是一个包装器…

第四章 基本数据

在第2章中&#xff0c;我们讨论了多种导入数据到R中的方法。遗憾的是&#xff0c;将你的数据表示为矩阵或数据框这样的矩形形式仅仅是数据准备的第一步。这里可以演绎Kirk船长在《星际迷航》“末日决战的滋味”一集中的台词&#xff08;这完全验明了我的极客基因&#xff09;&a…

聚观早报|春节档新片预售总票房破千万;苹果获可折叠iPhone新专利

今日要闻&#xff1a;比亚迪据称拟在越南建汽车零部件厂&#xff1b;2023 年春节档新片预售总票房破 7000 万&#xff1b;苹果获得可折叠 iPhone 新专利&#xff1b;北京汽车获1000台EU5 PLUS约旦订单&#xff1b;娃哈哈要解决100万农户农产品出路 比亚迪据称拟在越南建汽车零部…

C 语言目标文件

前言 一个 C 语言程序经编译器和汇编器生成可重定位目标文件&#xff0c;再经链接器生成可执行目标文件。那么目标文件中存放的是什么&#xff1f;我们的源代码在经编译以后又是怎么存储的&#xff1f; 文章为 《深入理解计算机系统》的读书笔记&#xff0c;更为详细的内容可…

【数据结构】双向链表

1.双向链表的结构2.双向链表的实现首先在VS里面的源文件建立test.c和List.c,在头文件里面建立List.hList.h:#pragma once #include <stdio.h> #include <stdlib.h> #include <assert.h> typedef int LTDateType; typedef struct ListNode {LTDateType data;s…

LeetCode 329. 矩阵中的最长递增路径(C++)*

思路&#xff1a; 1.用动态规划&#xff0c;但是时间复杂度太高&#xff0c;效率太低 2.使用常规的DFS&#xff0c;时间复杂度高&#xff0c;包含了太多重复无效遍历&#xff0c;会超时 3.在DFS的基础上使用记忆化搜索&#xff0c;帮助消去重复的遍历&#xff0c;提高效率 原题…

解决: 您目前无法访问 因为此网站使用了 HSTS。网络错误和攻击通常是暂时的,因此,此网页稍后可能会恢复正常

目录 问题描述 报错信息 问题原因 如何解决 参考资料 问题描述 您目前无法访问 因为此网站使用了 HSTS。网络错误和攻击通常是暂时的&#xff0c;因此&#xff0c;此网页稍后可能会恢复正常。 报错信息 今天使用Edge浏览器在访问一个平时常用的emoji网站时&#xff0c;…

springboot整合spring-security

在web开发中&#xff0c;安全性问题比较重要&#xff0c;一般会使用过滤器或者拦截器的方式对权限等进行验证过滤。此博客根据b站up主&#xff0c;使用demo示例进行展示spring-security的一些功能作用。 目 录 1、创建项目 2、编写controller 3、添加spring-security依赖 …

Spring Cloud OpenFeign 配置

最少的配置&#xff08;使用默认配置&#xff09; 最少/默认配置示例如下&#xff08;使用Nacos作为服务的注册与发现中心&#xff09;&#xff1a; application.properties server.port8082 spring.application.namenacos-consumer spring.cloud.nacos.discovery.server-ad…

[拆轮子] PaddleDetection中__shared__、__inject__ 和 from_config 三者分别做了什么

在上一篇中&#xff0c;PaddleDetection Register装饰器到底做了什么 https://blog.csdn.net/HaoZiHuang/article/details/128668393 已经介绍了 __shared__ 和 __inject__ 的作用: __inject__ 表示引入全局字典中已经封装好的模块。如loss等。__shared__为了实现一些参数的配…

excel函数技巧:函数TEXT七助数据大变身

如果函数有职业&#xff0c;那各函数的职业会是什么呢&#xff1f;别的先不说&#xff0c;就拿TEXT而言&#xff0c;它可以让日期变数字、数字变日期、阿拉伯数字变大写中文数字、金额元变万元&#xff0c;连IF的条件判断它也可以变出来…这简直就是当之无愧的变装女皇啊&#…

从0到1完成一个Node后端(express)项目(三、写接口、发起请求)

往期 从0到1完成一个Node后端&#xff08;express&#xff09;项目&#xff08;一、初始化项目、安装nodemon&#xff09; 从0到1完成一个Node后端&#xff08;express&#xff09;项目&#xff08;二、下载数据库、navicat、express连接数据库&#xff09; 写接口 我们看ex…

关于Linux部署Tomcat的访问问题

文章目录1.问题2.排除问题2.1检查Tomcat是否启动2.2检查防火墙&端口3.其他可能的问题3.1java的配置问题3.2可能出现了端口占用问题1.问题 在CentOS7系统的主机中配置好了Tomcat后发现通过默认端口无法访问到&#xff08;http://xx:xx:xx:xx:8080&#xff09; 2.排除问题 …

C语言在杨氏矩阵中找一个数

这道题大家都会做&#xff0c;使用暴力算法遍历整个数组。但是题目要求时间复杂度小于O&#xff08;n&#xff09;&#xff0c;这样做显然不合题意&#xff0c;所以&#xff0c;通过分析杨氏矩阵的特点&#xff0c;我们发现矩阵右上角的那个数为一行中最大的&#xff0c;一列中…