zoukankan      html  css  js  c++  java
  • 基于spring注解的定时任务-并行执行

    1、定时任务简述:指定触发规则后,按照一定的频率自动往复执行。默认只有一个单例化的线程池(始终只有一个线程)

             去处理定时任务;只有一个线程时,多个任务需要并行(同时)执行时会产生时间差【每个任务从执行开始

             到结束需要的时间不同,单线程情况下,只能等前一个任务结束才能开始执行下一个任务】,导致实际

            上每个任务不是按照指定的指定的频率执行。可以通过配置线程池来解决。

      1.1、非异步定时任务:从任务开始到结束都是同一个线程(即使执行过程中有线程阻塞)

        【当前任务执行完毕后才会根据任务执行条件再次触发

          异步定时任务(方法上有@Asycn注解): 从任务开始,假设进入阻塞状态,任务结束时和任务开始时不一定是

          同一个线程处理的【当前任务没有执行完毕,但任务执行条件触发则直接创建新线程执行任务

    2、相关依赖 

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>4.3.12.RELEASE </version> 
    </dependency>
    
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.2.3</version>
    </dependency>

    3、 简要的配置说明

      3.1添加命名空间 

    xmlns:task="http://www.springframework.org/schema/task
    http://www.springframework.org/schema/task 
    http://www.springframework.org/schema/task/spring-task-4.1.xsd

      3.2 spring配置文件【该文件需要spring读取

    <!-- 定时任务,配置需要扫描的包 -->
    <context:component-scan base-package="com.demo.quartz" />
    <!-- 用于激活那些已经在spring容器里注册过的bean(无论是通过xml的方式还是通过package scanning的方式)上面的注解 可不配置 --> <context:annotation-config/>
    <!-- 配置处理定时任务的线程池 --> <task:scheduler id="scheduler" pool-size="10" />
    <!-- 配置处理 异步定时任务的 线程池 -->
    <!--
      pool-size:线程池大小 keep-alive:线程最大空闲时间
      queue-capacity:队列大小(无线程可用时,其余任务放置队列中,队列放满后其他任务只能等待)
      rejection-policy:队列任务数达到最大时,处理其他任务的策略
    --> <task:executor id="taskExecutor" pool-size="10" keep-alive="2000" rejection-policy="DISCARD_OLDEST"
      queue-capacity="10" />
    <!-- 配置spring定时开关--> <task:annotation-driven executor="taskExecutor" scheduler="scheduler" />

      3.3、@Scheduled注解中属性设置 

        cron:执行任务触发频率规则:cron表达式详情查看另一博主介绍:http://biaoming.iteye.com/blog/39532   

    @Scheduled(fixedRate=3000) //上一次任务  开始执行后3秒 再次执行
    @Scheduled(fixedDelay=3000) //上一次    任务执行结束后 3秒,再次执行
    @Scheduled(initialDelay=1000,fixedDelay=3000) //第一次延时1秒执行,以后每次任务执行完后3秒再次执行  

    4、简单demo

    package com.demo.quartz;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    @Component
    @EnableScheduling //开启spring定时任务
    @Lazy(false)   //默认是true为懒下载,此处设置false
    public class TestQuartz {
        @Scheduled(cron="0/1 * * * * ?")
        public void test1() {
            //AsyncConfigurer
    //        ThreadPoolTaskScheduler  tpt  = new ThreadPoolTaskScheduler();
    //        System.err.println(tpt.getPoolSize());
            //org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean 
            //SchedulingConfigurer
            try {
                //  源码相关的类
                //ScheduledExecutorService
                //ScheduledTaskRegistrar 
                //TaskScheduler
                //ThreadPoolTaskScheduler
                //ThreadPoolTaskExecutor
                //org.springframework.scheduling.config.ScheduledTaskRegistrar;
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss");
            System.out.println(Thread.currentThread().getName()+"----------1-----------"+sdf.format(new Date()));
        }
        
        @Scheduled(cron="0/1 * * * * ?")
        public void test2() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss");  
            System.out.println(Thread.currentThread().getName()+"----------3-----------"+sdf.format(new Date()));
        }
        @Scheduled(cron="0/1 * * * * ?")
        public void test3() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss");
            System.out.println(Thread.currentThread().getName()+"----------4-----------"+sdf.format(new Date()));
        }
        
        @Async
        @Scheduled(cron="0/1 * * * * ?")
        public void test4() {
            SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss");
            try {
                System.err.println(Thread.currentThread().getName()+"----------2-----------查看线程名称-阻塞前"+sdf.format(new Date()));
                Thread.sleep(3000);
                System.err.println(Thread.currentThread().getName()+"----------2-----------查看线程名称-阻塞后"+sdf.format(new Date()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"----------2-----------"+sdf.format(new Date()));
        }
        
        @Async
        @Scheduled(cron="0/1 * * * * ?")
        public void test5() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss");
            System.out.println(Thread.currentThread().getName()+"----------5-----------"+sdf.format(new Date()));
        }
        @Async
        @Scheduled(cron="0/1 * * * * ?")
        public void test6() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss");
            System.out.println(Thread.currentThread().getName()+"----------6-----------"+sdf.format(new Date()));
        }
    }

    5、效果图

      --------------该数字(表示的任务编号)-----------------------

    6、定时任务执行流程源码解析

      https://unmi.cc/spring-schedule-runner-threads/ 

    人生没有彩排,每天都是现场直播!
  • 相关阅读:
    [转]vim 常用命令
    C语言运算符优先级顺序
    uboot
    linux 驱动开发 不定期更新
    [转]spdk 和nvme 预备知识1
    【转】聊聊 Linux IO
    [转]NVMe协议/ SSD控制器/ linux driver / open channel
    Ubuntu给应用程序创建一个启动图标
    Qt4.8.7+mingw4.8.2 环境搭建
    更改C编译器的缺省字节对齐方式__align(),__attribute((aligned (n))),#pragma pack(n)
  • 原文地址:https://www.cnblogs.com/northern-light/p/8594590.html
Copyright © 2011-2022 走看看