Java

您所在的位置:网站首页 triggertask Java

Java

2023-05-08 11:22| 来源: 网络整理| 查看: 265

作者:Mars酱

声明:本文章由Mars酱原创,部分内容来源于网络,如有疑问请联系本人。

转载:欢迎转载,转载前先请联系我!

前言

多线程解决了并发阻塞问题,但是不能方便的表达我们的定时方式,目前单体架构定时任务用的多的就应该是Spring Task中的注解方式了吧?

@Scheduled

scheduled注解常用的几个:

cron:支持灵活的cron表达式

fixedRate:固定频率。比如:2号线地铁每5分钟一趟,那么2号线的所有列车其实已经安排好了时刻表,所以每台准点发就行了,但是如果其中一趟晚点,那么下一趟就会延迟。

fixedDelay:固定时延。它的意思是表示上个任务结束,到下个任务开始的时间间隔。无论任务执行花费多少时间,两个任务间的间隔始终是一致的。

搞一搞 @Scheduled(fixedDelay = 1000 * 5) public void timerTaskA(){ // Mars酱 做业务a... } 复制代码

每间隔5秒执行一次

@Scheduled(cron = "0 0 1 * * ? ") public void timerTaskB(){ // Mars酱 做业务b... } 复制代码

这是支持cron表达式的,每天凌晨1点执行

Scheduled会阻塞吗?

我们来分析下Spring的源代码吧,如果我们用fixedRate或者fixedDelay,可以在 Spring 的@Scheduled的源代码实现部分找到如下代码:

会在一个registrar对象中添加注解相对应的对象,这个registrar是ScheduledTaskRegistrar对象:

private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar(); 复制代码

而这个ScheduledTaskRegistrar对象中有一个ScheduledExecutorService属性:

@Nullable private ScheduledExecutorService localExecutor; 复制代码

这个就是我们上篇中提到的多线程定时任务实现,继续在在ScheduledTaskRegistrar中又找到创建这个对象的方法:

/** * Schedule all registered tasks against the underlying * {@linkplain #setTaskScheduler(TaskScheduler) task scheduler}. */ @SuppressWarnings("deprecation") protected void scheduleTasks() { if (this.taskScheduler == null) { // 创建了一个单线程对象 this.localExecutor = Executors.newSingleThreadScheduledExecutor(); this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor); } if (this.triggerTasks != null) { for (TriggerTask task : this.triggerTasks) { addScheduledTask(scheduleTriggerTask(task)); } } if (this.cronTasks != null) { for (CronTask task : this.cronTasks) { addScheduledTask(scheduleCronTask(task)); } } if (this.fixedRateTasks != null) { for (IntervalTask task : this.fixedRateTasks) { addScheduledTask(scheduleFixedRateTask(task)); } } if (this.fixedDelayTasks != null) { for (IntervalTask task : this.fixedDelayTasks) { addScheduledTask(scheduleFixedDelayTask(task)); } } } 复制代码

这里第一个if判断就是创建那个localExecutor对象,使用的是newSingleThreadScheduledExecutor。在 Java | 一分钟掌握异步编程 | 3 - 线程异步 - 掘金 (juejin.cn)中提到过,这是创建单线程的线程池方式。那么一个单线程去跑多个定时任务是不是就会产生阻塞?来证明一下。

改写一下之前的例子,两个都是5秒执行,其中一个任务在执行的时候再延迟10秒,看是不是会影响到另一个线程的定时任务执行。改写后的代码如下:

import org.springframework.boot.SpringApplication; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import java.util.Date; /** * @author mars酱 */ @EnableScheduling public class MarsSpringScheduled { public static void main(String[] args) { SpringApplication.run(MarsSpringScheduled.class, args); } @Scheduled(fixedDelay = 5000) public void timerTaskA() throws InterruptedException { System.out.println(">> 这是a任务:当前时间:" + new Date()); Thread.sleep(10000); } @Scheduled(fixedDelay = 5000) public void timerTaskB() { System.out.println("> 这是a任务:当前时间:" + new Date()); Thread.sleep(10000); } } 复制代码

上面是任务A,下面是任务B,一上一下其乐融融:

/** * (这个类的说明) * * @author mars酱 */ @Service public class TimerTaskB { @Scheduled(fixedDelay = 2000) public void scheduler() { System.out.println("> 这是a任务:当前时间:" + new Date()); // Thread.sleep(10000); // } // //// @Async // @Scheduled(fixedDelay = 2000) // public void timerTaskB() { // System.out.println("


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3