SpringBoot 异步任务
Springboot异步任务
1、在编写之前,我们需要在Pom文件种添加 starter-web依赖组件,只有加入这个之后,才可以加入异步服务。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、需要在Springboot入口类也就是应用启动类加入 一个允许异类的注解,去表示当前应用需要使用异步任务
*@EnableScheduling //允许当前应用开启定时任务
* @EnableAsync //开启异步支持
* */
@EnableAsync //开启异步支持
@SpringBootApplication //表示当前是springboot应用
@EnableScheduling //允许当前应用开启定时任务
public class springapplicationstudy {

3、编写异步服务类
在处理异步服务的是时候,异步服务类需要被SpringBoot 扫描到,需要在异步类添加一个bean注解。@Service 或者Component
两者都是SpringBoot Bean 只不过@Component是基础类。
默认异步任务线程池配置,是不能重新利用线程池的,一个异步任务会起一个任务,这样会造成很大的一个资源浪费。
默认线程池的配置比较简单,一般情况需要定制优化一个线程池。
@Slf4j
@Service
public class AsyncService {
@Async
public void AsyncProcess() throws InterruptedException{
log.info("Async process Task Current thread name ---> {}",
Thread.currentThread().getName());//获取当前线程池的名称
TimeUnit.SECONDS.sleep(2); //Jave 并发的一个插件。
}
//有返回值
@Async
public Future <Integer> AsyncProcessHasReturn() throws InterruptedException {
log.info("Async Process [Has Return ],Get current thread name ----> {}",
Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(2);
return new AsyncResult<>(100);
}
}

4、编写线程池配置类
编写自定义异步线程池,既然是配置那么配置注解肯定少不了了。
之程序的开始添加 @Configuration
首先申明一个线程池的对象,然后对线程池进行优化配置。
实现 AsyncConfigurer 重写 两个方法
getAsyncExecutor 线程池配置
-
setCorePoolSize //线程池核心数量
-
setMaxPoolSize //最大线程池数量,超过核心的进程以外的进程
-
setQueueCapacity //缓冲队列的个数
-
setKeepAliveSeconds // 超出的核心进程数量以外的进程存活时间
-
setThreadNamePrefix // 线程池前缀
-
setWaitForTasksToCompleteOnShutdown //是否等待所有线程执行完毕之后关闭线程池 默认false
-
setAwaitTerminationSeconds //等待时间
//拒绝策略
-
AbortPolicy() //当线程池满了,队列也满了,它会直接废弃并且报出异常
-
CallerRunsPolicy() //如果执行程序已经关闭了,则会丢弃这个任务
-
DiscardOldestPolicy() //当线程数量等于最大线程数量,队列是满的情况下,它就会抛弃线程池种最后一个,并执行新传递进来的任务
-
DiscardPolicy() //当线程数量等于或最大线程数量,不做任何的操作
//线程池初始化
initialize
getAsyncUncaughtExceptionHandler 进程异常处理
实现并且重写
AsyncUncaughtExceptionHandler 中的 handleUncaughtException 方法
package com.caicai.springboot.study.config;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/*
*
* 自定义异步线程池的配置
*
* */
@Slf4j
@Configuration //配置类注解
public class AsyncConfig implements AsyncConfigurer {
//这里的Executor 是ThreadPool 它会返回一个线程池
//需要把这个注入到JavaBean
@Bean
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);//线程池核心数量
executor.setMaxPoolSize(20);//最大的线程池数量,也就超过核心池的时候,才会使用的
executor.setQueueCapacity(30);//缓冲队列的个数
executor.setKeepAliveSeconds(60);// 超出核心进程数量之外的线程数量的最大存活时间。默认60秒,超过则会被杀掉
executor.setThreadNamePrefix("Caicai_Async_");//线程名的前缀
executor.setWaitForTasksToCompleteOnShutdown(true);//是否等待所有线程执行完毕之后关闭线程池
executor.setAwaitTerminationSeconds(60); // 等待的时间,默认是0.也就是setWaitForTasksToCompleteOnShutdown 这个的等待时间
//拒绝策略
//用与被拒绝处理的一个处理程序,它直接在executor 的方法的调用线程中运行被拒绝的任务
executor.setRejectedExecutionHandler(
new ThreadPoolExecutor.AbortPolicy()
//AbortPolicy() 当线程池满了,队列也满了,它会直接废弃并且报出异常
//CallerRunsPolicy() //如果执行程序已经关闭了,则会丢弃这个任务
//DiscardOldestPolicy() 当线程数量等于最大线程数量,队列是满的情况下,它就会抛弃线程池种最后一个,并执行新传递进来的任务
//DiscardPolicy() 当线程数量等于或最大线程数量,不做任何的操作
);
//线程初始化
executor.initialize();
return executor;
}
// getAsyncUncaughtExceptionHandler 定义异常处理
/*
* 定义异步任务异常处理类,只会处理没有返回结果异步任务,有返回结果的任务会
* 交给客户端
*
* */
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
static class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler{
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
log.info("AsyncError:{} ,Method:{},Param:{}",throwable.getMessage(),method.getName(),
JSON.toJSONString(objects));//返回值,以json的形式返回
throwable.printStackTrace();//打印
//TODO 发送邮件或者手机短信
}
}
}
5、在异步服务类的异步注解添加指定线程池名称
@Async("getAsyncExecutor")//指定使用线程池名称
开开心心,上班!
快快乐乐,游玩!
及时行乐!

浙公网安备 33010602011771号