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监听
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();
}
}
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秒钟执行一次
}
}
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秒钟执行一次
}
}
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();
}
}
}
导入依赖:
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-core:核心工程
xxl-job-admin:调度中心。管理控制台,统一管理配置任务,并驱动任务的执行,提供了管理页面
xxl-job-executor-samples:执行器的案例工程。执行器本质就是一个工程,任务组。每一个执行器工程中可以定义多个任务
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.运行过程中,可以查看日志