博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
0113 spring定时任务和异步线程池
阅读量:4209 次
发布时间:2019-05-26

本文共 5257 字,大约阅读时间需要 17 分钟。

0113 spring的异步方法和定时任务

背景

spring的内容比较多,常规的知识必须进行系统化的学习,但是一些边缘的技术点,在实际工作中也是非常适用的;下面一一介绍和实践一次。

异步线程池

场景:下发任务跟执行任务分开。

比如我需要做一个数据统计。

场景 常规做法 改进做法
计算每天的统计数据,比如日新增,日活跃,日留存等 实时计算,计算和获取结果在同一个线程里完成 分两个部分:1.触发计算;2.异步完成计算;

spring中如何实现异步计算

  1. 系统中配置异步线程池;
  2. 在系统入口处配置@EnableAsync 注解;
  3. 在业务方法中标注  注解;

代码实例:

1.配置线程池,开启标记;

package com.springbootpractice.demo.spring.other.config;import com.google.common.util.concurrent.ThreadFactoryBuilder;import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.annotation.AsyncConfigurer;import org.springframework.scheduling.annotation.EnableAsync;import java.util.concurrent.Executor;import java.util.concurrent.LinkedBlockingDeque;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;/** * 说明:自定义异步线程池和异常处理 * @author carter * 创建时间: 2020年01月13日 10:12 上午 **/@EnableAsync@Configurationpublic class AsyncConfig implements AsyncConfigurer {    /**     * @return 线程池     */    @Override    public Executor getAsyncExecutor() {        return new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,                new LinkedBlockingDeque<>(10000),                new ThreadFactoryBuilder().setDaemon(true).setNameFormat("demo_spring_other_%s").build(),                new ThreadPoolExecutor.DiscardPolicy()        );    }    /**     * 可以结合监控系统,监控该异常,进行告警     * @return 异常处理     */    @Override    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {        return new SimpleAsyncUncaughtExceptionHandler();    }}

2.使用代码

package com.springbootpractice.demo.spring.other.service;import lombok.extern.slf4j.Slf4j;import org.springframework.scheduling.annotation.Async;import org.springframework.stereotype.Service;import java.time.LocalDate;import java.util.concurrent.TimeUnit;/** * 说明:统计数据计算业务代码 * @author carter * 创建时间: 2020年01月13日 10:27 上午 **/@Service@Slf4jpublic class AsyncSummaryDataService {    @Async    public void calculateDayNewData(LocalDate day) {        try {            TimeUnit.SECONDS.sleep(10);        } catch (InterruptedException e) {            e.printStackTrace();        }        log.info("calculateDayNewData 执行线程:{}", Thread.currentThread().getName());    }    @Async    public void calculateDayLeftData(LocalDate day) {        try {            TimeUnit.SECONDS.sleep(20);        } catch (InterruptedException e) {            e.printStackTrace();        }        log.info("calculateDayLeftData 执行线程:{}", Thread.currentThread().getName());    }    @Async    public void calculateDayActiveData(LocalDate day) {        try {            TimeUnit.SECONDS.sleep(30);        } catch (InterruptedException e) {            e.printStackTrace();        }        log.info("calculateDayActiveData 执行线程:{}", Thread.currentThread().getName());    }}

  1. 测试代码
@Autowired    private AsyncSummaryDataService asyncSummaryDataService;    @Test    void asyncTest() {        asyncSummaryDataService.calculateDayActiveData(LocalDate.now());        asyncSummaryDataService.calculateDayLeftData(LocalDate.now());        asyncSummaryDataService.calculateDayNewData(LocalDate.now());    }

输出:

2020-01-13 10:38:02.084  INFO 35059 --- [_spring_other_1] c.s.d.s.o.s.AsyncSummaryDataService      : calculateDayLeftData 执行线程:demo_spring_other_12020-01-13 10:38:12.085  INFO 35059 --- [_spring_other_0] c.s.d.s.o.s.AsyncSummaryDataService      : calculateDayActiveData 执行线程:demo_spring_other_02020-01-13 10:38:12.092  INFO 35059 --- [_spring_other_1] c.s.d.s.o.s.AsyncSummaryDataService      : calculateDayNewData 执行线程:demo_spring_other_12020-01-13 10:38:12.108  INFO 35059 --- [           main] c.s.d.s.o.service.SummaryDataService     : calculateDayActiveData 执行线程:main2020-01-13 10:38:32.114  INFO 35059 --- [           main] c.s.d.s.o.service.SummaryDataService     : calculateDayLeftData 执行线程:main2020-01-13 10:38:42.117  INFO 35059 --- [           main] c.s.d.s.o.service.SummaryDataService     : calculateDayNewData 执行线程:main

定时任务

B端应用,可能需要一些定时任务,比如月末报表。在spring中启用定时任务非常简单,步骤如下:

使用步骤

  1. 标准@EnableScheduling 在启动入口处;
  2. 在使用的业务方法上标注@Scheduled注解;

 

配置项 说明
cron cron表达式
zone 时区
fixedDelay,fixedDelayString 固定延迟时间,两个任务之间的执行延迟;milliseconds
fixedRate,fixedRateString 固定频率,两个任务之间固定的执行间隔
milliseconds
initialDelay,initialDelayString 初始化延迟,springIOC初始化完毕之后多少延迟之后开始执行首次任务的延迟
milliseconds

cron表达式不说了,可以直接使用工具生成: 推荐一个;

实例: 0 0 0 ? 每天0点开始执行;

实例代码:

package com.springbootpractice.demo.spring.other.service;import lombok.extern.slf4j.Slf4j;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.scheduling.annotation.Schedules;import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;/** * 说明:TODO * @author carter * 创建时间: 2020年01月13日 11:14 上午 **/@Service@Slf4jpublic class ScheduleTaskService {    @Schedules({            @Scheduled(initialDelay = 5 * 1000, fixedRate = 10 * 1000)    })    public void generateMonthReport() {        try {            TimeUnit.SECONDS.sleep(2);        } catch (InterruptedException e) {            e.printStackTrace();        }        log.info("执行月报表计算");    }}

小结

1. 学会了使用spring内置的异步线程池来把某些同步方法改造成异步方法;

1. 学会了使用sping内置的定时任务来完成某些工作;

原创不易,转载请注明出处,欢迎多沟通交流

你可能感兴趣的文章
ACM POJ catalogues[转载]
查看>>
ACM经历总结[转载]
查看>>
C/C++文件操作[转载]
查看>>
专业计划
查看>>
小米笔试:最大子数组乘积
查看>>
常见的排序算法
查看>>
5.PyTorch实现逻辑回归(二分类)
查看>>
6.PyTorch实现逻辑回归(多分类)
查看>>
8.Pytorch实现5层全连接结构的MNIST(手写数字识别)
查看>>
9.PyTorch实现MNIST(手写数字识别)(2卷积1全连接)
查看>>
hdu 3460 Ancient Printer(trie tree)
查看>>
中间数
查看>>
KMP求前缀函数(next数组)
查看>>
KMP
查看>>
poj 3863Business Center
查看>>
Android编译系统简要介绍和学习计划
查看>>
Android编译系统环境初始化过程分析
查看>>
user2eng 笔记
查看>>
DRM in Android
查看>>
ARC MRC 变换
查看>>