定时任务的多种实现——xxl-job

定时任务

    • 场景
    • 特征
    • 实现
      • 1.死循环
      • 2.Timer定时器
      • 3.juc中定时任务线程池
      • 4.延时队列
      • 5.SpringScheduling框架
    • xxl-job
      • xxl-job结构:
      • xxl-job的入门程序:

场景

	1.购物车数据同步 redis --> mysql 
	2.报表
	3.布隆过滤器数据同步
	4.MQ消息重发

特征

	1.时间驱动
	2.批量处理
	3.异步执行

实现

	1.jdk:死循环、Timer定时器、juc中定时任务线程池、延时队列等等
	2.spring:SpringScheduling框架 @EnableScheduling @Scheduled
	3.quartz框架
	4.分布式定时任务:xxl-job、elastic-job等等
	5.MQ:延时队列 + 死信队列
	6.netty框架:时间轮
	7.redis监听

1.死循环

package com.atguigu.gmall.scheduled.jdk;

import java.util.concurrent.TimeUnit;

public class ScheduledDemo {
    public static void main(String[] args) {
        System.out.println("初始化时间:" + System.currentTimeMillis());
        new Thread(() -> {
            while (true){
                try {
                    TimeUnit.SECONDS.sleep(10);//每隔10秒钟执行一次
                    System.out.println("死循环实现——任务执行时间:" + System.currentTimeMillis());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "").start();
    }
}

输出结果:
定时任务的多种实现——xxl-job_第1张图片

2.Timer定时器

package com.atguigu.gmall.scheduled.jdk;

import java.util.Timer;
import java.util.TimerTask;

public class ScheduledDemo {

    public static void main(String[] args) {
        System.out.println("初始化时间:" + System.currentTimeMillis());
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("这是Timer定时器任务:" + System.currentTimeMillis());
            }
        }, 5000, 10000);//延迟5秒钟,每隔10秒钟执行一次
    }
}

输出结果:定时任务的多种实现——xxl-job_第2张图片

3.juc中定时任务线程池

package com.atguigu.gmall.scheduled.jdk;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledDemo {
    public static void main(String[] args) {
        System.out.println("初始化时间:" + System.currentTimeMillis());
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            System.out.println("这是通过定时任务线程池:" + System.currentTimeMillis());
        }, 5, 10, TimeUnit.SECONDS);//延迟5秒钟,每隔10秒钟执行一次
    }
}

输出结果:
定时任务的多种实现——xxl-job_第3张图片

4.延时队列

package com.atguigu.gmall.scheduled.jdk;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class ScheduledDemo {
    public static void main(String[] args) {
        System.out.println("初始化时间:" + System.currentTimeMillis());

        new DelayTask().schedule(() -> {
            System.out.println("这是通过延时队列实现了定时任务:" + System.currentTimeMillis());
        }, 5, 10, TimeUnit.SECONDS);//延迟5秒钟,每隔10秒钟执行一次
    }
}

class DelayTask implements Delayed {
    private static final DelayQueue<DelayTask> DELAY_QUEUE = new DelayQueue<>();
    // 定时任务执行时间
    private long timeout;
    /**
     * 延时队列会自旋调用该方法,如果该方法的返回值小于等于0,该任务可以出队
     * @param unit
     * @return
     */
    @Override
    public long getDelay(TimeUnit unit) {
        return this.timeout - System.currentTimeMillis();
    }

    /**
     * 排队方法
     * @param o
     * @return
     */
    @Override
    public int compareTo(Delayed o) {
        return (int) (this.timeout - ((DelayTask)o).timeout);
    }

    /**
     *
     * @param task 任务
     * @param delay 延时时间
     * @param period 周期时间
     * @param unit 时间单位
     */
    public void schedule(Runnable task, int delay, int period, TimeUnit unit){
        try {
            this.timeout = System.currentTimeMillis() + unit.toMillis(delay);
            int flag = 1;
            while (true){
                if (flag != 1) {
                    this.timeout += unit.toMillis(period);
                }
                DELAY_QUEUE.put(this);
                DELAY_QUEUE.take();
                new Thread(task).start();
                flag++;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * @param task 任务
     * @param delay 延时时间
     * @param unit 时间单位
     */
    public void schedule(Runnable task, int delay, TimeUnit unit){
        try {
            this.timeout = System.currentTimeMillis() + unit.toMillis(delay);
            DELAY_QUEUE.put(this);
            DELAY_QUEUE.take();
            new Thread(task).start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出结果:
定时任务的多种实现——xxl-job_第4张图片

5.SpringScheduling框架

导入依赖:


       org.springframework.boot
       spring-boot-starter-web

启动类上加注解:

@EnableScheduling
package com.atguigu.gmall.scheduled.spring;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledDemo {
    /**
     * fixedDelay/fixedRate:每间隔特定时间执行一次
     * initialDelay:延迟多少时间执行
     * cron表达式:秒 分 时 日 月 星期
     */
    @Scheduled(cron = "0/35 * * * * *")//每分钟的0秒开始 每35秒钟执行一次
    //@Scheduled(fixedRate = 5000, initialDelay = 5000)//延时5秒 每隔5秒执行一次
    //@Scheduled(fixedRate = 5000)//每隔5秒执行一次  fixedRate和fixedDelay效果一样
    //@Scheduled(fixedDelay = 5000)//每隔5秒执行一次
    public void test(){
        System.out.println("这是spring的定时任务:" + System.currentTimeMillis());
    }
}

输出结果:
定时任务的多种实现——xxl-job_第5张图片

xxl-job

xxl-job结构:

xxl-job-core:核心工程
xxl-job-admin:调度中心。管理控制台,统一管理配置任务,并驱动任务的执行,提供了管理页面
xxl-job-executor-samples:执行器的案例工程。执行器本质就是一个工程,任务组。每一个执行器工程中可以定义多个任务

xxl-job的入门程序:

1.搭建调度中心
	1.把doc/db/tables_xxl_job.sql导入到mysql
	2.修改调度中心的配置文件
		1.端口号 2.数据源 3.accessToken
	3.打包:mvn clean package -Dmaven.skip.test=true
	4.运行: java -jar xxl-job-admin.xxx.jar 
	5.集群:1.DB一致 2.系统时间一致 3.nginx作负载均衡

2.搭建执行器工程,定义任务
	1.引入依赖:
		xxl-job-core 
	2.修改执行器配置(copy)
		1.端口号 2.调度中心地址 3.accessToken 4.appName 5.日志目录
	3.java配置:XxlJobConfig.java
	
	4.定义任务:
		

3.在调度中心配置任务
	1.配置执行器
		appname要和上边执行工程配置文件中的appname一致
		title:描述
		注册方式:自动注册
		
	2.配置任务:
		路由策略:第一个 最后一个 轮训 随机 故障转移 忙碌转移 最不经常使用 最近最久未使用 一致性hash 
		cron表达式:秒 分 时 日 月 星期 年
			具体值:
				秒、分:0-59
				时:0-23
				日:1-31之间
				月:1-12之间 英文简称或者全称
				星期:1-7之间 英文的简称或者全称
			间隔:/
			列表:,
			范围:-
			任意值:*
				? 只能在日期或者星期上使用,日期和星期不能同时指定,也不能同时为* 或者 ?
		运行模式:BEAN
		阻塞策略:单机串行 丢弃后续调度 覆盖之前调度
	
	3.运行过程中,可以查看日志

你可能感兴趣的:(java,定时任务)