SpringBoot整合Quartz实现动态定时任务(三十四)

news2024/9/25 17:05:29

二八佳人体似酥,腰间仗剑斩愚夫。虽然不见人头落,暗里教君骨髓枯。

上一章简单介绍了 SpringBoot定时任务(三十三) ,如果没有看过,请观看上一章

关于 Quartz, 可以看老蝴蝶之前的文章: https://blog.csdn.net/yjltx1234csdn/category_9953970.html

本章节参考了文章: springboot整合quartz实现定时任务的动态修改,启动,暂停等操作

在这个大佬的基础上,进行了扩充。

SpringBoot 整合 Quartz

pom.xml 添加依赖

<!--添加 spring-boot-starter-quartz的依赖-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>
    <!-- json 工具 -->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
    </dependency>

application.yml 文件配置

# 引入 数据库的相关配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.100.252:3306/springboot?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true
    username: root
    password: abc123
  #配置 quartz
  quartz:
    #初始化数据库脚本路径,默认使用classpath:org/quartz/impl/jdbcjobstore/tables_@@platform@@.sql路径下的脚本
    #注意,放置的是 spring.quartz 下面
    #持久化到数据库方式
    job-store-type: jdbc
    # 初始化Quartz表结构,项目第一次启动配置程always,然后改成never 否则已生成的job会被初始化掉
    initialize-schema: never
    properties:
      org:
        quartz:
          scheduler:
            instanceName: MyScheduler
            instanceId: AUTO
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            tablePrefix: QRTZ_
            isClustered: true
            clusterCheckinInterval: 10000
            useProperties: false
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true

需要先初始化表结构。

在这个 jar 包上, quartz-2.3.2.jar org.quartz.impl.jdbcjobstore.tables.mysql_innodb.sql

在相应的库上面 执行该 sql 文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OgqFt3Bc-1672825073638)(images/image-20230104164042059.png)]

业务代码实现定时任务

创建定时任务类, 继承 QuartzJobBean

创建定时任务类: MyQuartzJob

//继承 抽象类  QuartzJobBean
public class MyQuartzJob extends QuartzJobBean {
   @Autowired
   private UserService userService;
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {

        System.out.println(" 执行定时任务: " + context.getJobDetail().getKey());
        // 获取参数
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        User user = new User();
        if (!ObjectUtils.isEmpty(jobDataMap)) {
            user.setName(jobDataMap.getString("name"));
            user.setAge(jobDataMap.getInt("age"));
            user.setSex(jobDataMap.getString("sex"));
            user.setDescription(jobDataMap.getString("description"));
        }
        userService.addUser(user);
    }
}

配置 JobDetail 和 Trigger

@Configuration
public class QuartzConfig {
    @Bean
    public JobDetail myJobDetail(){
        JobDetail jobDetail = JobBuilder.newJob(MyQuartzJob.class)
                .withIdentity("myQuartzJob","system")
                //JobDataMap可以给任务execute传递参数
                .usingJobData("name","两个蝴蝶飞")
                .usingJobData("age",26)
                .storeDurably()
                .build();
        return jobDetail;
    }
    @Bean
    public Trigger myTrigger(){
        Trigger trigger = TriggerBuilder.newTrigger()
                .forJob(myJobDetail())
                .withIdentity("myTrigger1","myTriggerGroup1")
                .usingJobData("job_trigger_param","job_trigger_param1")
                .startNow()
                //.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever())
            // 固化的 cron 表达式
                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
                .build();
        return trigger;
    }
}

执行程序

启动类上不需要添加 @EnableScheduling 注解

@SpringBootApplication
@Log4j2
public class JobApplication {
    public static void main(String[] args) {
        SpringApplication.run(JobApplication.class,args);
        log.info("运行定时任务启动成功");
    }
}

如果有任务的话,服务器停止之后还会执行那个时候的任务,后面会变正常,每隔5s 执行一次, 任务参数也可以获取到。

2023-01-04 16:47:24.015  INFO 23132 --- [  restartedMain] top.yueshushu.learn.JobApplication       : 运行定时任务启动成功
2023-01-04 16:47:34.025  INFO 23132 --- [_ClusterManager] o.s.s.quartz.LocalDataSourceJobStore     : ClusterManager: detected 1 failed or restarted instances.
2023-01-04 16:47:34.025  INFO 23132 --- [_ClusterManager] o.s.s.quartz.LocalDataSourceJobStore     : ClusterManager: Scanning for instance "Yuejl1672822021469"'s failed in-progress jobs.
2023-01-04 16:47:34.100  INFO 23132 --- [_ClusterManager] o.s.s.quartz.LocalDataSourceJobStore     : ClusterManager: ......Freed 1 acquired trigger(s).
 执行定时任务: system.myQuartzJob
2023-01-04 16:47:34.342  INFO 23132 --- [eduler_Worker-1] t.y.learn.service.UserServiceImpl        : 执行添加员工的操作,User(id=null, name=两个蝴蝶飞, sex=null, age=26, description=null)
 执行定时任务: system.myQuartzJob
2023-01-04 16:47:34.618  INFO 23132 --- [eduler_Worker-2] t.y.learn.service.UserServiceImpl        : 执行添加员工的操作,User(id=null, name=两个蝴蝶飞, sex=null, age=26, description=null)
 执行定时任务: system.myQuartzJob
2023-01-04 16:47:34.833  INFO 23132 --- [eduler_Worker-3] t.y.learn.service.UserServiceImpl        : 执行添加员工的操作,User(id=null, name=两个蝴蝶飞, sex=null, age=26, description=null)
 执行定时任务: system.myQuartzJob
2023-01-04 16:47:35.112  INFO 23132 --- [eduler_Worker-4] t.y.learn.service.UserServiceImpl        : 执行添加员工的操作,User(id=null, name=两个蝴蝶飞, sex=null, age=26, description=null)
 执行定时任务: system.myQuartzJob
2023-01-04 16:47:40.130  INFO 23132 --- [eduler_Worker-5] t.y.learn.service.UserServiceImpl        : 执行添加员工的操作,User(id=null, name=两个蝴蝶飞, sex=null, age=26, description=null)
 执行定时任务: system.myQuartzJob
2023-01-04 16:47:45.164  INFO 23132 --- [eduler_Worker-6] t.y.learn.service.UserServiceImpl        : 执行添加员工的操作,User(id=null, name=两个蝴蝶飞, sex=null, age=26, description=null)
 执行定时任务: system.myQuartzJob
2023-01-04 16:47:50.110  INFO 23132 --- [eduler_Worker-7] t.y.learn.service.UserServiceImpl        : 执行添加员工的操作,User(id=null, name=两个蝴蝶飞, sex=null, age=26, description=null)

动态实现定时任务调度

上面的方式是写死在程序当中的,也存在修改不方便的情况。

实体接收数据 QuartzBean

@Data
public class QuartzBean implements Serializable {
    /** 任务id */
    private String  id;

    /** 任务名称 */
    private String jobName;

    /** 任务执行类 */
    private String jobClass;

    /** 组名 */
    private String groupName;

    /** 任务 参数信息 */
    private String jobParam;

    /** 任务状态 启动还是暂停*/
    private Integer status;

    /** 任务运行时间表达式 */
    private String cronExpression;
}

工具类 QuartzUtils

/**
 * 任务工具类
 *
 * @author yuejianli
 * @date 2023-01-04
 */
public class QuartzUtils {
    /**
       获取所有的定时任务
     * @throws Exception
     */
    public static List<QuartzBean> getAllJob(Scheduler scheduler){
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
        List<QuartzBean> jobList = new ArrayList();
        try {
            Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
            for (JobKey jobKey : jobKeys) {
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
                    QuartzBean job = new QuartzBean();
                    job.setJobName(jobKey.getName());
                    job.setGroupName(jobKey.getGroup());
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    job.setStatus(Trigger.TriggerState.NORMAL.equals(triggerState)?1:0);
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        job.setCronExpression(cronExpression);
                    }
                    JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                    JobDataMap jobDataMap = jobDetail.getJobDataMap();
                    String[] keys = jobDataMap.getKeys();
                    if (keys != null && keys.length > 0){
                        Map<String,String> paramMap = new HashMap<>(keys.length,1.0f);
                        for (String key: keys) {
                            paramMap.put(key, jobDataMap.get(key).toString());
                        }
                        String paramStr = JSON.toJSONString(paramMap);
                        job.setJobParam(paramStr);
                    }
                    Class<? extends Job> jobClass = jobDetail.getJobClass();
                    job.setJobClass(jobClass.getName());
                    jobList.add(job);
                }
            }

        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return jobList;
    }

    /**
     * 创建定时任务 定时任务创建之后默认启动状态
     * @param scheduler   调度器
     * @param quartzBean  定时任务信息类
     * @throws Exception
     */
    public static void createScheduleJob(Scheduler scheduler, QuartzBean quartzBean){
        try {
            //获取到定时任务的执行类  必须是类的绝对路径名称
            //定时任务类需要是job类的具体实现 QuartzJobBean是job的抽象类。
            Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass());
            // 构建定时任务信息
            JobBuilder jobBuilder = JobBuilder.newJob(jobClass).withIdentity(quartzBean.getJobName(), quartzBean.getGroupName());

            // 设置参数
            Map<String,String> paramHashMap = JSON.parseObject(quartzBean.getJobParam(), HashMap.class);
            if (!ObjectUtils.isEmpty(paramHashMap)){
                paramHashMap.forEach(
                        (param,paramValue)->{
                            jobBuilder.usingJobData(param,paramValue);
                        }
                );
            }
            JobDetail jobDetail = jobBuilder
                    .storeDurably()
                    .build();
            // 设置定时任务执行方式
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());
            // 构建触发器trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzBean.getJobName()).withSchedule(scheduleBuilder).build();
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (ClassNotFoundException e) {
            System.out.println("定时任务类路径出错:请输入类的绝对路径");
        } catch (SchedulerException e) {
            System.out.println("创建定时任务出错:"+e.getMessage());
        }
    }

    /**
     * 根据任务名称暂停定时任务
     * @param scheduler  调度器
     * @param jobKeyName    定时任务名称
     * @throws SchedulerException
     */
    public static void pauseScheduleJob(Scheduler scheduler, String jobKeyName){
        String[] jobNameGroupArr = jobKeyName.split("\\.");
        JobKey jobKey = JobKey.jobKey(jobNameGroupArr[1],jobNameGroupArr[0]);
        try {
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            System.out.println("暂停定时任务出错:"+e.getMessage());
        }
    }

    /**
     * 根据任务名称恢复定时任务
     * @param scheduler  调度器
     * @param jobKeyName    定时任务名称
     * @throws SchedulerException
     */
    public static void resumeScheduleJob(Scheduler scheduler, String jobKeyName) {
        String[] jobNameGroupArr = jobKeyName.split("\\.");
        JobKey jobKey = JobKey.jobKey(jobNameGroupArr[1],jobNameGroupArr[0]);
        try {
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            System.out.println("启动定时任务出错:"+e.getMessage());
        }
    }

    /**
     * 根据任务名称立即运行一次定时任务
     * @param scheduler     调度器
     * @param jobKeyName       定时任务名称
     * @throws SchedulerException
     */
    public static void runOnce(Scheduler scheduler, String jobKeyName){
        String[] jobNameGroupArr = jobKeyName.split("\\.");
        JobKey jobKey = JobKey.jobKey(jobNameGroupArr[1],jobNameGroupArr[0]);
        try {
            scheduler.triggerJob(jobKey);
        } catch (SchedulerException e) {
            System.out.println("运行定时任务出错:"+e.getMessage());
        }
    }

    /**
     * 更新定时任务
     * @param scheduler   调度器
     * @param quartzBean  定时任务信息类
     * @throws SchedulerException
     */
    public static void updateScheduleJob(Scheduler scheduler, QuartzBean quartzBean)  {
        deleteScheduleJob(scheduler,quartzBean.getGroupName()+"."+quartzBean.getJobName());
        createScheduleJob(scheduler,quartzBean);
    }

    /**
     * 根据定时任务名称从调度器当中删除定时任务
     * @param scheduler 调度器
     * @param jobKeyName   定时任务名称
     * @throws SchedulerException
     */
    public static void deleteScheduleJob(Scheduler scheduler, String jobKeyName) {
        String[] jobNameGroupArr = jobKeyName.split("\\.");
        JobKey jobKey = JobKey.jobKey(jobNameGroupArr[1],jobNameGroupArr[0]);
        try {
            if (ObjectUtils.isEmpty(jobKey)){
                return ;
            }
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            System.out.println("删除定时任务出错:"+e.getMessage());
        }
    }
}

编写定时任务

这个与具体的业务有关, 需要提前创建好。

如 这儿老蝴蝶定义两个任务, 一个有参数,一个无参数。

无参数任务:

/**
 * 任务, 是 空参数
 *
 * @author yuejianli
 * @date 2023-01-04
 */
@Slf4j
public class MyTask1 extends QuartzJobBean {

    @Autowired
    private UserService userService;
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
            userService.addUser(null);
            log.info("   空参数任务 :" + context.getJobDetail().getKey());
    }
}

有参数任务:

@Slf4j
public class MyTask2 extends QuartzJobBean {

    @Autowired
    private UserService userService;
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        log.info("   有参数任务 :" + context.getJobDetail().getKey());
        if (ObjectUtils.isEmpty(jobDataMap)) {
            userService.addUser(null);
            return ;
        }
        User user = new User();
        user.setName(jobDataMap.getString("name"));
        user.setAge(jobDataMap.getInt("age"));
        user.setSex(jobDataMap.getString("sex"));
        user.setDescription(jobDataMap.getString("description"));
        userService.addUser(user);
    }
}

控制实现类

/**
 * 定时任务 controller
 */
@RestController
@RequestMapping("/quartz/")
public class ScheduledController {
    /**
     注入任务调度
     */
    @Resource
    private Scheduler scheduler;

    @RequestMapping("/getAll")
    public List<QuartzBean>  getAll()  {
        try {
            return QuartzUtils.getAllJob(scheduler);
        } catch (Exception e) {
            return null;
        }
    }

    @RequestMapping("/createJob")
    public String  createJob(@RequestBody QuartzBean quartzBean)  {
        try {
            QuartzUtils.createScheduleJob(scheduler,quartzBean);
        } catch (Exception e) {
            return "创建失败";
        }
        return "创建成功";
    }

    @RequestMapping("/pauseJob")
    public String pauseJob(String jobName)  {
        try {
            QuartzUtils.pauseScheduleJob (scheduler,jobName);
        } catch (Exception e) {
            return "暂停失败";
        }
        return "暂停成功";
    }

    @RequestMapping("/runOnce")
    @ResponseBody
    public String  runOnce(String jobName)  {
        try {
            QuartzUtils.runOnce (scheduler,jobName);
        } catch (Exception e) {
            return "运行一次失败";
        }
        return "运行一次成功";
    }

    @RequestMapping("/resume")
    @ResponseBody
    public String  resume(String jobName)  {
        try {

            QuartzUtils.resumeScheduleJob(scheduler,jobName);
        } catch (Exception e) {
            return "重新开启失败";
        }
        return "重新开启成功";
    }

    @RequestMapping("/delete")
    @ResponseBody
    public String  delete(String jobName)  {
        try {

            QuartzUtils.deleteScheduleJob(scheduler,jobName);
        } catch (Exception e) {
            return "重新开启失败";
        }
        return "重新开启成功";
    }

    @RequestMapping("/update")
    @ResponseBody
    public String  update(@RequestBody QuartzBean quartzBean)  {
        try {
            QuartzUtils.updateScheduleJob(scheduler,quartzBean);
        } catch (Exception e) {
            return "更新失败";
        }
        return "更新成功";
    }
}

测试运行

获取所有的任务 /getAll

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RZRgx1OQ-1672825073639)(images/image-20230104171631765.png)]

删除任务 /delete

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l676JYtD-1672825073639)(images/image-20230104171831389.png)]

再次查询,没有数据了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HC6cyV6f-1672825073640)(images/image-20230104171901615.png)]

创建定时任务 createJob

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9aWFveDf-1672825073640)(images/image-20230104172206212.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VRDswWWM-1672825073640)(images/image-20230104172235795.png)]

暂时定时任务 /pauseJob

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jxgzTWYW-1672825073641)(images/image-20230104172401038.png)]

不继续打印了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xlvsGQ4t-1672825073641)(images/image-20230104172418070.png)]

手动运行一次定时任务 runOnce

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7A7usW3o-1672825073641)(images/image-20230104172554759.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HjG6VjSf-1672825073641)(images/image-20230104172536994.png)]

只跑一次

重启定时任务 /resume

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9QijFBKZ-1672825073641)(images/image-20230104172724978.png)]

在这里插入图片描述

更新定时任务 /update

修改 cron 表达式和 参数的值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cr7z10yz-1672825073642)(images/image-20230104173421680.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0yw7XX10-1672825073642)(images/image-20230104173410719.png)]

本章节的代码放置在 github 上:

https://github.com/yuejianli/springboot/tree/develop/SpringBoot_QuartzJob

谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!

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

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

相关文章

【云原生】k8s的集群调度

k8s中的list-watch机制1.1 list-watc机制的概念运用Kubernetes 是通过 List-Watch 的机制进行每个组件的协作&#xff0c;保持数据同步的&#xff0c;每个组件之间的设计实现了解耦。用户是通过 kubectl 根据配置文件&#xff0c;向 APIServer 发送命令&#xff0c;在 Node 节点…

Android 基本控件

一、TextView TextView是一个文本框 1.id id是这个textview的唯一id 格式是id/(自定义ID) 图中Id是tv_one 每一个TextView都是一个对象 可以使用TextView的ID通过findViewById&#xff08;&#xff09;方法获取到这个View对象 setText是设置这个TextView的文本&#xff0c…

TiDB丨 从MySQL迁移至TiDB的常见问题及解决方案

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录一、前言二、GC设置过长的问题为什么在MySQL里可设置&#xff0c;保留更多的历史数据&#xff0c;而TiDB不行&#xff1f;TiDB中历史版本过多问题及排查方法二、SQL调…

Python解题 - CSDN周赛第20期 - 逆波兰 / 后缀表达式

不知不觉已经参加了19场比赛了&#xff0c;由于参赛次数多&#xff0c;排名竟然稀里糊涂地上升到第一&#xff0c;受宠若惊&#xff0c;赶紧截图保存纪念一下。 正好又赶上元旦&#xff0c;新的2023年&#xff0c;希望CSDN的周赛能越办越好&#xff0c;尽量少出bug&#xff0c;…

P1047 [NOIP2005 普及组] 校门外的树

题目 [NOIP2005 普及组] 校门外的树 题目描述 某校大门外长度为 lll 的马路上有一排树&#xff0c;每两棵相邻的树之间的间隔都是 111 米。我们可以把马路看成一个数轴&#xff0c;马路的一端在数轴 000 的位置&#xff0c;另一端在 lll 的位置&#xff1b;数轴上的每个整数…

批量化工程项目的实施过程

最近的批量化项目存在方案设计上的问题&#xff0c;导致很严重的后果。 1、各个相关方都需要投入较大的精力来处理此事&#xff1b; 2、投入的时间、金钱及人员等均在其中&#xff1b; 3、方案需要进行重新的验证&#xff0c;总体项目工程的周期进一步被压缩&#xff1b; 4…

21-InnoDB引擎底层存储和缓存原理

到目前为止&#xff0c;MySQL对于我们来说还是一个黑盒&#xff0c;我们只负责使用客户端发送请求并等待服务器返回结果&#xff0c;表中的数据到底存到了哪里&#xff1f;以什么格式存放的&#xff1f;MySQL是以什么方式来访问的这些数据&#xff1f;这些问题我们统统不知道。…

【C++ Primer】阅读笔记(1):基础

目录 简介类型选择(经验准则)当一个算术表达式既有int,又有无符号数时,int会转换为无符号数对象初始化与赋值的区别声明与定义全局变量与局部变量示例引用指针与引用的区别不可以将int变量直接赋值给指针,即便这个int变量是0const对象必须初始化参考结语简介 Hello! 非常…

pdf转换器电脑版免费,好用的办公操作软件集合

工作中太多的文件格式需要我们进行操作了&#xff0c;各种各样的文件可以打开的软件经常是不同的。就像是PDF文件&#xff0c;如果没有在电脑安装对应的可以打开的软件&#xff0c;可能我们就没办法直接查看文件内容。而且这种情况也不是偶然出现&#xff0c;可能还会随着我们文…

信息系统项目管理师的论文如何提高?

简单点来说吧&#xff01;也适合软考小白来看&#xff01; 信息系统项目管理师论文要写几道题&#xff1f;没有参加过信息系统项目管理师考试的考生对于论文科目考试不是很了解&#xff0c;那么信息系统项目管理师论文到底要写几道题呢&#xff1f; 软考高级信息系统项目管理…

振弦采集模块辅助功能寄存器之低功耗休眠

振弦采集模块辅助功能寄存器之低功耗休眠 在收到休眠指令后&#xff0c;完成当次测量后立即进入低功耗的休眠模式&#xff0c;休眠模式下&#xff0c; VDD 电流可降至 1mA 左右&#xff0c;当收到数字接口任意数据后自动唤醒。此功能会使硬件看门狗失效&#xff0c;存在模块意…

关于项目型和职能型组织结构的思考和笔记

1、区别项目型还是职能型&#xff0c;最根本的要点在于&#xff0c;沟通渠道必须通过谁&#xff08;负责人是谁&#xff0c;是项目经理还是职能经理&#xff0c;谁有沟通渠道控制权&#xff09;&#xff1b; 2、沟通渠道的控制权取决于利益的优先权&#xff08;例如&#xff1…

前端常用处理时间方法

项目上用到很多时间格式,写了一些处理时间的方法,也可以用第三方库,下面是我自己项目封装的一下方法,命名瞎写的,有些方法是关联的,很多没有怎么完善,记录一下,兼容ios时间问题,时间太赶没有完善,将就用下,人和程序有一个人跑就行 获取当前时间戳 getTodayTomorrowTtem export…

求树的直径(史上最详细,匠心之作,限时免费看)

一&#xff0c;题目SPOJ PT07Z, Longest path in a tree一.定义树上任意两节点之间最长的简单路径即为树的「直径」。二&#xff0c;解法做法 1. 两次 DFS过程:首先从任意节点y, 开始进行第一次 DFS&#xff0c;到达距离其最远的节点&#xff0c;记为 z&#xff0c;然后再从 z开…

ARM S5PV210 中断体系与外部中断实战

一、中断体系介绍 1、什么是中断 中断的发明是用来解决宏观上的并行需要的。宏观就是从整体上来看&#xff0c;多件事情都完成了。微观上的并行&#xff0c;就是指的真正的并行&#xff0c;就是精确到每一秒甚至每一刻&#xff0c;多个事情都是在同时进行的。宏观上面的并行并…

OQC与Cyxtera将量子计算应用于数据中心

牛津量子电路&#xff08;OQC&#xff09;正与云服务公司Cyxtera合作&#xff0c;在数据中心安装量子计算机&#xff0c;方便用户在其本地数据集上运行量子算法。 在葡萄牙里本举行的网络峰会上&#xff0c;牛津量子电路&#xff08;OQC&#xff09;首席执行官ILana Wisby谈到了…

【力扣经典题目】环形链表,判断链表是否有环

题目描述&#xff1a; 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链…

【Unity】新手初学Animation实现人物移动

【Unity】新手初学Animation实现人物移动 需求&#xff1a;开发影院系统&#xff0c;希望加入Avatar人物&#xff0c;在其中行走和坐下 环境&#xff1a;Unity2021.3 新手初学Animation教程&#xff1a;BV1BW41187fL Avatar人物模型资源&#xff1a;学长网盘链接分享 Animation…

【电动汽车充电站有序充电调度的分散式优化】基于蒙特卡诺和拉格朗日的电动汽车优化调度(分时电价调度)(Matlab代码实现)

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

实习------SpringMVC 框架学习

Spring MVC 是什么 &#xff08;了解&#xff09;Spring MVC&#xff08;全称 Spring Web MVC&#xff09;是 Spring 框架提供的一款基于 MVC 模式的轻量级 Web 开发框架&#xff0c;是 Spring 为表示层&#xff08;UI&#xff09;开发提供的一整套完备的解决方案。注&#xff…