当我们需要实现并发、异步等操作时,通常都会使用到ThreadPoolTaskExecutor
ThreadPoolTaskExecutor是spring core包中的,而ThreadPoolExecutor是JDK中的JUC。ThreadPoolTaskExecutor是对ThreadPoolExecutor进行了封装处理。
自己在之前写多线程代码的时候都是这么玩的executor=Executors.newCachedThreadPool();但是有一次在大量数据的时候由于入库速度远大于出库速度导致内存急剧膨胀最后悲剧了重写代码,原来spring 早就给我们做好封装了。
祖类都是调用Executor接口
ThreadPoolTaskExecutor通常通过XML方式配置,或者通过Executors
的工厂方法进行配置
配置文件spring-thread.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" lazy-init="false">
<!-- 线程池维护线程的最少数量 -->
<property name="corePoolSize" value="32"/>
<!-- 允许的空闲时间 -->
<property name="keepAliveSeconds" value="180"/>
<!-- 线程池维护线程的最大数量 -->
<property name="maxPoolSize" value="64"/>
<!-- 缓存队列 -->
<property name="queueCapacity" value="2048"/>
<!-- 不允许回收核心线程 -->
<property name="allowCoreThreadTimeOut" value="false"/>
<!-- 线程组名 -->
<property name="threadGroupName" value="xiao-zhen-group-name"/>
<!-- 对拒绝task的处理策略 -->
<property name="rejectedExecutionHandler">
<bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy"/>
</property>
</bean>
</beans>
java代码
/**
*
* 业务代码提交类
*/
@Autowired
private ThreadPoolExecutorService threadPoolExecutorService ;
// 提交线程任务,传具体实现类,构造器参数自己定义
threadPoolExecutorService.submit(new SubTestClass(RequestBO requestBO));
/**
*
* 线程提交类
*/
@Component
public class ThreadPoolExecutorService {
/**
* 公用线程池
*/
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
/**
* 提交任务到线程池中执行
*
* @param testClass任务
*/
public void submit(TestClass testClass) {
threadPoolTaskExecutor.submit(testClass);
}
}
public class SubTestClass extends TestClass{
/**
* 构造器
*
* @param baseRequestBO 请求参数
*/
public SubTestClass(RequestBO requestBO ) {
super.requestBO = requestBO ;
}
/**
* 设置任务名
*/
@Override
void setTaskName() {
super.taskName = "线程名称";
}
@Override
protected void executeTask(RequestBO requestBO) {
super.executeTask(requestBO);
// 对抽象父类进行重写,具体业务代码写在子类中,实现具体的业务逻辑
}
....... 对父类其他方法重写
}
// 抽象类实现 Runnable接口
public abstract class TestClass implements Runnable {
private RequestBO requestBO;
/**
* 任务名
*/
@Getter
protected String taskName;
/**
* 设置任务名
*/
abstract void setTaskName();
/**
* 前置处理器
*/
protected void preHandle() {
log.info("【异步任务{}将要开始执行】", taskName);
}
/**
* 执行异步任务
*/
protected void executeTask(RequestBO requestBO) {
log.info("【异步任务{}将开始执行中,执行参数是:{}】", taskName, requestBO);
}
/**
* 重写run方法
*/
@Override
public void run() {
try {
// 设置任务名
setTaskName();
// 前置处理器
preHandle();
// 执行异步任务
executeTask(requestBO);
// 后置处理器
postHandle();
} catch (Throwable throwable) {
// 异常处理器
exceptionCaught(throwable);
} finally {
// 执行完毕处理器
afterCompletion();
}
}
/**
* 后置处理器
*/
protected void postHandle() {
log.info("【异步任务{}将要执行结束】", taskName);
}
/**
* 异常处理器
*
* @param throwable 异常
*/
protected void exceptionCaught(Throwable throwable) {
log.error("【异步任务{}执行异常,请求参数是:{},异常原因是:】", taskName, baseRequestBO, throwable);
}
/**
* 执行完毕处理器
*/
protected void afterCompletion() {
log.info("【异步任务{}执行完毕】", taskName);
}
}