美文网首页
定时器(注解方式)

定时器(注解方式)

作者: 寂静的春天1988 | 来源:发表于2020-06-12 12:06 被阅读0次

原文:https://www.cnblogs.com/domi22/p/9418433.html

1、spring boot使用注解实现定时器

@EnableScheduling
@Component
public class TestTimer {
    @Scheduled(cron="*/1 * * * * ?")
    public void testOne() {
        System.out.println("第一个"+"每1秒执行一次"+Thread.currentThread().getName());
    }
 
    @Scheduled(fixedRate=1000)
    public void testTwo() {
        System.out.println("第二个"+"每1秒执行一次"+Thread.currentThread().getName());
    }
}

这样项目启动的时候定时器就启动了,但是通过打印线程名可以发现,这两个任务是同一个线程。

如果将第二个任务睡眠10秒,模拟延时。

@EnableScheduling
@Component
public class TestTimer {
    @Scheduled(cron="*/1 * * * * ?")
    public void testOne() {
        System.out.println("第一个"+"每1秒执行一次"+Thread.currentThread().getName());
    }
 
    @Scheduled(fixedRate=1000)
    public void testTwo() {
        System.out.println("第二个"+"每1秒执行一次"+Thread.currentThread().getName());
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

会发现不但自己的任务丢失了,也造成了其他任务的丢失。
问题1:单线程任务丢失
解决办法:采用异步的方式执行调度任务,配置 Spring 的 @EnableAsync,在执行定时任务的方法上标注 @Async配置任务执行池

@EnableScheduling
@EnableAsync
@Component
public class TestTimer {
    
    @Async
    @Scheduled(cron="*/1 * * * * ?")
    public void testOne() {
        System.out.println("第一个"+"每1秒执行一次"+Thread.currentThread().getName());
    }
    @Async
    @Scheduled(fixedRate=1000)
    public void testTwo() {
        System.out.println("第二个"+"每1秒执行一次"+Thread.currentThread().getName());
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

注意:@Async所使用的线程池容量为100
3.配置线程池大小
虽然上面的方式已经解决了我们的问题,但是总觉得不太好,有时候我们需要异步执行任务,但是又不需要这么多的线程的时候,我们可以使用下面的配置来设置线程池的大小
配置文件:

@Configuration
public class AsyncConfig {

    @Bean("taskExecutor")
    public Executor taskExecutor1() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("taskExecutor-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);
        return executor;
    }

}

问题2:在分布式系统下,重复执行的问题。

解决方式1:可以使用redis的分布式锁保证spring schedule集群只执行一次。 redis分布式锁是通过setnx命令实现的。该命令的作用是,当往redis中存入一个值时,会先判断该值对应的key是否存在,如果存在则返回0,如果不存在,则将该值存入redis并返回1。(但是在分布式跨时区部署的时候,依然无法避免重复执行)

解决方式2:可以通过使用shedlock将spring schedule上锁。详细见:https://segmentfault.com/a/1190000011975027

问题3:如果使用异步多线程方式,会有并发安全问题。
如果想有的定时任务不考虑并发安全使用@Async注解,有的定时任务需要考虑线程并发使用同步阻塞方式。

@EnableScheduling
@EnableAsync 
@Component
public class TestTimer {
    
    @Scheduled(cron="*/1 * * * * ?")
    public void testOne() throws InterruptedException {
        System.out.println("任务1====>"+Thread.currentThread().getName());
        Thread.sleep(10000); //模拟延时
    }
    
    @Async
    @Scheduled(cron="*/1 * * * * ?")
    public void testTwo() throws InterruptedException {
        System.out.println("任务2====>"+Thread.currentThread().getName());
    }
}

发现任务2还是会被任务1阻塞住,好像没什么好办法?

待解决:问题3

相关文章

  • java定时任务

    方式一:基于注解@Scheduled实现简单定时器 DemoApplication文件 MySchedule文件 ...

  • 定时器(注解方式)

    原文:https://www.cnblogs.com/domi22/p/9418433.html 1、spring...

  • swift Timer 定时器

    方式1 方式2 这种定时器的创建需要使用 fire 来启动定时器。否则,该定时器不起作用。如果定时器不添加到 Ru...

  • Spring boot 定时器(九)

    主要是添加注解的方式进行 2、Spring boot 在定时器中进行数据库操作,在jpa框架进行增删改查操作数据库...

  • SpringBoot自定义注解

    spring注解:一般在记录日志、定时器中使用非常方便,在springmvc框架广泛应用,可以注解的随处可见,近几...

  • JavaScript

    javascript引入方式 定时器

  • MyBatis 注解方式的基本用法

    什么是MyBatis的注解方式 MyBatis的注解方式就是将SQL语句直接写在接口上。在MyBatis注解SQL...

  • 注解方式

    注解的优势:简化配置。减少配置。一般在工作中:使用注解替换部分配置,但是一般使用注解+配置的混合模式。 配置多了,...

  • 最简单的Spring AOP教程|基于@AspectJ的AOP精

    Spring除了支持Schema方式配置AOP,还支持注解方式,使用@AspectJ风格的切面声明。 注解方式启用...

  • Spring学习笔记

    目录 1.XML方式使用Spring2.注解方式使用Spring3.注解方式测试 一、XML方式使用Spring ...

网友评论

      本文标题:定时器(注解方式)

      本文链接:https://www.haomeiwen.com/subject/eyjptktx.html