简单快捷优雅的实现一个定时任务

什么场景

获取token

    最近也是遇到了一些烦恼,比如获取 token ,一天内获取的次数有限,每次获取到的 token 也是有一定的有效期。针对这种情况,其实需要我们定时的去获取token,并且刷新到缓存中,但是如果在多台机子的情况下,我们需要去做一个分布式锁,每次只保证有一台机子去获取token。

 

单机实现生产消费

    自己生产自己消费,其实就是一端往一个队列丢数据,另一端往队列里面消费数据,当然是阻塞队列。当然这种情况下肯定不好的,因为操作都是基于内存的,重启机子的时候会丢失数据。所以这种也只是针对 数据量不是持续的都有。一阵一阵的。那为什么要用定时任务呢? 因为在消费一段,where(true) 去拿数据是不是会导致cpu巨高。所以一般都会使用定时任务,每个几秒去看一下队列里面是否有数据。

 

怎么简单优雅的实现呢

    下面就简单的来一个栗子。解释一下 @PostConstruct注解的作用,被注解的方法,构造函数之后,set执行之前执行。

/** * @author JZWen * @date 2020/11/25 */@Servicepublic class TaskService {    private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();    private volatile TaskJob taskJob = null;    @PostConstruct    public void startup() {        System.out.println("-----------start up-----------");        scheduledExecutorService.scheduleWithFixedDelay(new TaskJob(), 2, 10, TimeUnit.SECONDS);        System.out.println("-----------end down------------");    }    public TaskJob getJob() {        if (taskJob != null) {            return taskJob;        }        synchronized (TaskJob.class) {            if (taskJob == null) {                taskJob = new TaskJob();            }        }        return taskJob;    }}

 

执行 job 线程

/** * @author JZWen * @date 2020/11/25 */public class TaskJob implements Runnable{    @Override    public void run() {        System.out.println("开始执行任务-------------------");        try {            Thread.sleep(1000L);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("执行任务结束-------------------");    }}

 

执行结果

-----------start up----------------------end down------------2020-11-25 15:25:52.441  INFO 16864 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'2020-11-25 15:25:52.878  INFO 16864 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8088 (http) with context path ''2020-11-25 15:25:52.882  INFO 16864 --- [           main] com.github.wetest.WxTestApplication      : Started WxTestApplication in 5.793 seconds (JVM running for 9.259)开始执行任务-------------------执行任务结束-------------------开始执行任务-------------------执行任务结束-------------------开始执行任务-------------------执行任务结束-------------------开始执行任务-------------------执行任务结束-------------------开始执行任务-------------------执行任务结束-------------------开始执行任务-------------------执行任务结束-------------------

 

Job 有依赖,拿到的是null

    因为 @PostConstruct注解的作用,被注解的方法,构造函数之后,set执行之前执行。所以如果当前类要是使用 @Autowired 或者 @Value 注解的属性,拿到的是null。这点切记。怎么解决这个呢,很简单,在job的构造放里面放入你的依赖,将依赖传过去。如下,job 依赖 wxTemplateMsgService

 

/** * @author JZWen * @date 2020/11/25 */@Servicepublic class TaskService {    private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();    private volatile TaskJob taskJob = null;    @Autowired    private WxTemplateMsgService wxTemplateMsgService;    @PostConstruct    public void startup() {        System.out.println("-----------start up-----------");        scheduledExecutorService.scheduleWithFixedDelay(new TaskJob(wxTemplateMsgService), 2, 10, TimeUnit.SECONDS);        System.out.println("-----------end down------------");    }    public TaskJob getJob(WxTemplateMsgService wxTemplateMsgService) {        if (taskJob != null) {            return taskJob;        }        synchronized (TaskJob.class) {            if (taskJob == null) {                taskJob = new TaskJob(wxTemplateMsgService);            }        }        return taskJob;    }}

 

 

/** * @author JZWen * @date 2020/11/25 */public class TaskJob implements Runnable{    private WxTemplateMsgService wxTemplateMsgService;    public TaskJob(WxTemplateMsgService wxTemplateMsgService) {        this.wxTemplateMsgService = wxTemplateMsgService;    }    @Override    public void run() {        System.out.println("开始执行任务-------------------");        try {            wxTemplateMsgService.send(new WxTemplateMsgInfo());            Thread.sleep(1000L);        } catch (Exception e) {            e.printStackTrace();        }        System.out.println("执行任务结束-------------------");    }}

 

最后一点,job 抛异常,定时任务会停止

    要是job里面抛异常的话,整个定时任务会停止,所以一定要自己catch 异常并处理。

 

目前这个操作,我在公司还两块业务用到了,感觉比搭建什么 quartz 更快,但是没有他那么灵活,对于业务量不大的服务可以使用这种方式。奥里给!!

 

 

 

 

 

欢迎小兄弟们关注我!!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值