@Scheduled阻塞导致未执行生效

简介: @Scheduled阻塞导致未执行生效


  • 任务【1】
@Component
public class Test01 {
    // 每秒执行一次
    @Scheduled(cron = "0/1 * * * * ? ")
    public void test() {
        // 时分秒
        String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"));
        // 日志打印
        System.out.println(nowTime + "   任务【1】执行  线程:" + Thread.currentThread().getName());
    }
}
• 11
  • 任务【2】
@Component
public class Test02 {
    // 每5秒执行一次
    @Scheduled(cron = "0/5 * * * * ? ")
    public void test() {
        String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"));
        System.out.println(nowTime + "   任务【2】执行  线程:" + Thread.currentThread().getName());
        try {
            // 模拟耗时任务,阻塞2s
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  • 运行

  • 原因
  • 由程序运行后的打印结果可以发现两个任务均是使用的同一线程。
  • 任务【1】应该是每秒执行一次的,但是执行时间上可以发现,任务【1】的执行时间不是连续的,这就说明有时间点是任务【1】没有执行的,而这些时间点恰好任务【2】正在执行中,单线程的原因线程此时阻塞,从而导致这些时间点任务【1】没有执行。
  • 解决添加@Async注解或者使用自定义线程池执行任务在上面的任务【1】和任务【2】的@Scheduled注解上面添加一个注解@Async即可
  1. 多线程执行定时任务

注意:对@Async进行自定义配置,内部也是通过创建ThreadPoolExecutor线程池来执行。

  1. 全局配置:实现SchedulingConfigurer接口
@Configuration
public class ScheduledConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        // 自定义调度器,设置为一个支持定时及周期性的任务执行的线程池,这里初始3个线程
        scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(3));
    }
}

统一配置后不需要添加@Async注解或者创建线程池实现异步执行定时任务

定时任务执行的线程达到多线程执行,任务【1】执行时间连续,没有出现未执行的情况,且线程也是反复使用的三个。

自定义调度器的时候,只能设置TaskSchedulerScheduledExecutorService类型,除此之外的类型都会报错


相关文章
|
Java Spring
@Scheduled 多个定时任务同时执行
这篇文章主要介绍了springBoot @Scheduled实现多个任务同时开始执行,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
873 0
|
6月前
|
Java 调度 Python
解决方案:APScheduler定时任务不执行,报错Run time of job ... was missed by ...
解决方案:APScheduler定时任务不执行,报错Run time of job ... was missed by ...
732 0
解决方案:APScheduler定时任务不执行,报错Run time of job ... was missed by ...
|
Java API 调度
多线程实现Spring定时任务@Scheduled
多线程实现Spring定时任务@Scheduled
|
Java 调度
定时任务@Scheduled 和 异步@Async
定时任务@Scheduled 和 异步@Async
|
调度
解决使用@Scheduled创建任务时无法在同一时间执行多个任务的BUG
解决使用@Scheduled创建任务时无法在同一时间执行多个任务的BUG
184 0
|
调度 数据库
Quartz的Scheduler的关闭和挂起,并发控制(四)中
Quartz的Scheduler的关闭和挂起,并发控制(四)中
1708 0
Quartz的Scheduler的关闭和挂起,并发控制(四)中
|
调度
Quartz的Scheduler的关闭和挂起,并发控制(四)上
Quartz的Scheduler的关闭和挂起,并发控制(四)上
455 0
Quartz的Scheduler的关闭和挂起,并发控制(四)上
Quartz的Scheduler的关闭和挂起,并发控制(四)下
Quartz的Scheduler的关闭和挂起,并发控制(四)下
478 0
Quartz的Scheduler的关闭和挂起,并发控制(四)下
|
Java 调度
【高并发】ScheduledThreadPoolExecutor与Timer的区别和简单示例
JDK 1.5开始提供ScheduledThreadPoolExecutor类,ScheduledThreadPoolExecutor类继承ThreadPoolExecutor类重用线程池实现了任务的周期性调度功能。在JDK 1.5之前,实现任务的周期性调度主要使用的是Timer类和TimerTask类。本文,就简单介绍下ScheduledThreadPoolExecutor类与Timer类的区别,ScheduledThreadPoolExecutor类相比于Timer类来说,究竟有哪些优势,以及二者分别实现任务调度的简单示例。
280 0
【高并发】ScheduledThreadPoolExecutor与Timer的区别和简单示例