zoukankan      html  css  js  c++  java
  • Spring Boot (29) 定时任务

    使用场景:数据定时增量同步,定时发送邮件,爬虫定时抓取

    定时任务概述

      定时任务:顾名思义就是在特定/指

    定的时间进行工作,比如我们的手机闹钟,他就是一种定时的任务。

    实现方式:

      1.Timer:JDK自带的java.util.Timer;通过调度java.util.TimerTask的方式 让程序按照某一个频率执行,但不能在指定时间运行,一般使用较少。

      2.ScheduledExecutorService:JDK1.5增加的,位于Java.util.concurrent包种,是基于线程池设计的定时任务类,每个调度任务都会被分配到线程池中,并发执行,互不影响。

      3.Spring Task:spring 3.0以后新增了task,一个轻量级的Quartz,功能够用,用法简单。

      4.Quartz:功能最为强大的调度器,可以让程序在指定时间执行,也可以按照某一个频率执行,他还可以动态开关,但是配置起来比较复杂,现如今开源社区中已经很多基于Quartz 实现的分布式定时任务项目。

    Timer方式

      基于Timer实现的定时调度,目前应用较少,不推荐使用

        @GetMapping("/test")
        public String test() {
    
            TimerTask timerTask = new TimerTask() {
                @Override
                public void run() {
                    System.out.println("执行任务"+ LocalDateTime.now());
                }
            };
            Timer timer = new Timer();
            //参数1 需要执行的任务 参数2 延迟时间毫秒 参数3 间隔时间毫秒
            timer.schedule(timerTask,5000,3000);
    
            return "test";
        }

    ScheduledExecutorService

      基于ScheduledExecutorService实现的调度任务,它与TImer很类似,但它的效果更好,多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中有一个因任务报错没有捕获抛出的异常,其他任务便会自动终止运行,使用scheduledExecutorService可以规避这个问题

        @GetMapping("/cheduled")
        public String cheduled() {
    
            ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
            //参数1具体执行的任务 2首次执行的延迟时间 3任务执行间隔 4间隔时间单位
            service.scheduleAtFixedRate(()->System.out.println("执行任务"+LocalDateTime.now()),0,3, TimeUnit.SECONDS);
    
            return "cheduled";
        }

    Spring Task(关键)

    导入依赖

    在pom.xml中添加spring-boot-starter-web依赖即可,它包含了spring-context,定时任务相关的就属于这个JAR下的org.springframework.scheduling包中

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    定时任务

    @Scheduled 定时任务的核心

      cron:cron表达式,根据表达式循环执行,与fixedRate属性不同的是它将时间进行了切割

      fixeRate:每隔多久执行一次,无视工作时间(@Scheduled(fixedRate = 1000))假设第一次工作时间为2018-06-15 00:00:00,工作时长为5秒,那么下次任务的时间就是 2018-06-15 00:00:05)

      initialDelay:第一次执行延迟时间,只是做延迟的设定,与fixedDelay关系密切,配合使用。

    @Async 代表任务可以进行一步工作,由原本的串行改为并行

    package com.spring.boot.utils;
    
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    import java.time.LocalDateTime;
    
    @Component
    public class SpringTaskDemo {
        @Async
        @Scheduled(cron = "0/1 * * * * *")
        public void scheduled1() throws InterruptedException {
            Thread.sleep(3000);
            System.out.println("scheduled1 每1秒执行一次" + LocalDateTime.now());
        }
    
        @Scheduled(fixedRate = 1000)
        public void scheduled2() throws InterruptedException {
            Thread.sleep(3000);
            System.out.println("scheduled2 每1秒执行一次" + LocalDateTime.now());
        }
    
    
        @Scheduled(fixedRate = 3000)
        public void scheduled3() throws InterruptedException {
            Thread.sleep(5000);
            System.out.println("scheduled3 航次执行完毕后间隔3秒继续执行" + LocalDateTime.now());
        }
    }

    cron表达式在线生成: http://www.pdtools.net/tools/becron.jsp

    启动类中@EnableScheduling注解 表示开启对@Scheduled注解的解析;同时new ThreadPoolTaskScheduler()也是相当的关键,默认情况下的private volatile int poolSize = 1;这就导致了多个任务的情况下容易出现竞争情况(多个任务的情况下,如果第一个任务没执行完毕,后续的任务将会进入等待状态)。

    @EnableAsync 代表开启@Async异步的解析,并行化运行

    @EnableAsync
    @EnableScheduling
    @SpringBootApplication
    public class BootApplication{
    
        public static void main(String[] args) {
            SpringApplication.run(BootApplication.class,args);
        }
    
        @Bean
        public TaskScheduler taskScheduler(){
            ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
            taskScheduler.setPoolSize(10);
            return taskScheduler;
        }
    }

    测试

    启动项目 观察日志信息如下:

    scheduled2 每1秒执行一次2018-06-14T17:33:42.245
    scheduled1 每1秒执行一次2018-06-14T17:33:43.030
    scheduled1 每1秒执行一次2018-06-14T17:33:44.009
    scheduled3 航次执行完毕后间隔3秒继续执行2018-06-14T17:33:44.244
    scheduled1 每1秒执行一次2018-06-14T17:33:45.011
    scheduled2 每1秒执行一次2018-06-14T17:33:45.249
    scheduled1 每1秒执行一次2018-06-14T17:33:46.008
    scheduled1 每1秒执行一次2018-06-14T17:33:47.008
    scheduled1 每1秒执行一次2018-06-14T17:33:48.010
    scheduled2 每1秒执行一次2018-06-14T17:33:48.254
    scheduled1 每1秒执行一次2018-06-14T17:33:49.005
    scheduled3 航次执行完毕后间隔3秒继续执行2018-06-14T17:33:49.247
    scheduled1 每1秒执行一次2018-06-14T17:33:50.008
    scheduled1 每1秒执行一次2018-06-14T17:33:51.006
    scheduled2 每1秒执行一次2018-06-14T17:33:51.258
    scheduled1 每1秒执行一次2018-06-14T17:33:52.006
    scheduled1 每1秒执行一次2018-06-14T17:33:53.008
    scheduled1 每1秒执行一次2018-06-14T17:33:54.007
    scheduled3 航次执行完毕后间隔3秒继续执行2018-06-14T17:33:54.252
    scheduled2 每1秒执行一次2018-06-14T17:33:54.262
    scheduled1 每1秒执行一次2018-06-14T17:33:55.007
    scheduled1 每1秒执行一次2018-06-14T17:33:56.007
    scheduled1 每1秒执行一次2018-06-14T17:33:57.005
    scheduled2 每1秒执行一次2018-06-14T17:33:57.266
    scheduled1 每1秒执行一次2018-06-14T17:33:58.007
    scheduled1 每1秒执行一次2018-06-14T17:33:59.006
    scheduled3 航次执行完毕后间隔3秒继续执行2018-06-14T17:33:59.257
  • 相关阅读:
    Java 中常用的数据源
    Restful风格API接口开发springMVC篇
    Maven的作用到底是什么
    Java中常用的数据源
    数据库死锁问题 及 解决方法
    string中执行sql语句
    提高mysql千万级大数据SQL查询优化30条经验
    JAVA对象转换JSON
    oracle分页查询
    jdk8环境变量 jdk8图解安装 java8安装
  • 原文地址:https://www.cnblogs.com/baidawei/p/9184142.html
Copyright © 2011-2022 走看看