IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java定时任务与分布式定时任务 -> 正文阅读

[Java知识库]Java定时任务与分布式定时任务

Java定时任务与分布式定时任务


业务场景:

  • 订单下单之后15分钟后,用户未付款,系统需要自动取消订单
  • 红包24小时未被查收,需要延迟执退还业务;
  • 超过7天,自动收货

1. JDK原生

使用JUC 提供的newScheduledThreadPool来执行定时任务

public class ScheduledExecutor {
    public static void main(String[] args) {
        // 创建任务队列,起10个线程
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
        // 执行任务:1秒 后开始执行,每5秒执行一次
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务: "+new Date());
            }
        },1,5, TimeUnit.SECONDS);
    }
}

2. Spring

使用Spring提供的@Scheduled 配置任务类,在启动类上添加@EnableScheduling

@Component
public  class ScheduleWork {
    @Scheduled(cron = "5/3 * * * * ? ")
    public void doJob() {
        System.out.println("spring 定时器 :"+ new Date());
    }
}
// 启动类加上注解,表示启用定时任务
@EnableScheduling
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

或者使用@Configuration定义配置类注解,在任务类上同时使用@EnableScheduling@Scheduled

@Configuration
@EnableScheduling
public class SomeJob {
    @Scheduled(cron = "5/3 * * * * ? ")
    public void someTask() {
        System.out.println("更改注解位置的方式  ");
    }
}

这种方式有个缺点,那就是执行周期写死在代码里了,没有办法动态改变,要想改变只能修改代码在重新部署启动微服务.

3.Spring + 数据库

  • 启动类

    @EnableScheduling
    @SpringBootApplication
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    
  • 配置类

    @Configuration
    public class ScheduleConfig implements SchedulingConfigurer {
        @Autowired
        private ApplicationContext context;
    
        @Autowired
        private SpringScheduleService scheduleService;
    
        @Override
        public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
            // 查询出所有的任务列表,这里使用的是mybatis,查询的MySQL数据库、
            List<SpringScheduledCron> workList = scheduleService.findAllWorkList();
            for (SpringScheduledCron scheduledCron : workList) {
                Class<?> clazz;
                Object task;
    
                try {
                    // 使用反射获取Class类对象
                    clazz = Class.forName(scheduledCron.getCronKey());
                    // 获取spring容器中初始化的bean对象
                    task  = context.getBean(clazz);
                } catch (ClassNotFoundException e) {
                    throw new IllegalArgumentException("该class有误:"+scheduledCron.getCronKey() + "----",e);
                }
             
                // 所有定时任务类在微服务启动的时候,就会被自动注册到Spring的定时任务里
                 // 动态改变执行周期
                scheduledTaskRegistrar.addTriggerTask((Runnable) task,triggerContext -> {
                    // 获取定时任务表达式,执行时间
                    String cronExpression = scheduleService.findByCronKey(scheduledCron.getCronKey()).getCronExpression();
                    return new CronTrigger(cronExpression).nextExecutionTime(triggerContext);
                });
            }
    
        }
    
        // 开启线程池,去处理多个定时任务
        @Bean
        public Executor taskExecutor() {
            return Executors.newScheduledThreadPool(10);
        }
    }
    
  • 任务类

    @Component
    public class DynamicTask implements Runnable {
        private Logger logger =  LoggerFactory.getLogger(getClass());
        private int i;
    
        @Override
        public void run() {
            logger.info("Task---线程 id :{}, 任务执行 :{}",Thread.currentThread().getId(),++i);
        }
    }
    

4.Spring+Redis

同上,只是将原本放在关系型数据中的任务列表,存储在Redis

5.分布式定时任务

RabbitMQ

最适合此类场景的,是使用消息队列的延迟队列。可以查看这篇文章:《RabbitMQ消息中间件技术精讲(五)》

quartz

依赖于MySQL,使用相对简单,可多节点部署,通过竞争数据库锁来保证只有一个节点执行任务。没有图形化管理页面,使用相对麻烦。

elastic-job-lite

依赖于Zookeeper,通过zookeeper的注册与发现,可以动态的添加服务器。

xxl-job

国产,依赖于MySQL,基于竞争数据库锁保证只有一个节点执行任务,支持水平扩容。可以手动增加定时任务,启动和暂停任务。

参考文章:
《在Spring Boot中优雅的实现定时任务》
《【每日鲜蘑】分布式环境下的定时任务》

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:18:55  更:2022-03-15 22:21:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:26:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码