Springboot集成定时器和多线程异步处理
/**
- 线程池异步配置
*/
@Configuration
@EnableAsync
public class ThreadExecutorConfig
implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(5);
// 设置最大线程数
executor.setMaxPoolSize(7);
// 设置队列容量
executor.setQueueCapacity(20);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置默认线程名称
executor.setThreadNamePrefix("PASCAL-");
// 设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new MyAsyncUncaughtExceptionHandler();
}
}
启动类上要记得添加异步和开启定时器的标签
@SpringBootApplication
@EnableScheduling
@Async
public class MultithreadingApplication {
public static void main(String[] args) {
SpringApplication.run(MultithreadingApplication.class, args);
}
}
业务逻辑方法:
@Async
@Scheduled(initialDelay=1000,fixedDelay = 5000)
public void test(){
SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss");
try {
logger.info("当前线程为:"+Thread.currentThread().getName()+",方法开始时间为:"+format.format(new Date()));
Thread.sleep(10000);
logger.info("当前线程为:"+Thread.currentThread().getName()+",方法结束时间为:"+format.format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
对于@Schedule注解的使用方法:
点进去可以看到有几个可选参数:
fixedDelay:控制方法执行的间隔时间,是以上一次方法执行完开始算起,如上一次方法执行阻塞住了,那么直到上一次执行完,并间隔给定的时间后,执行下一次
fixedRate:是按照一定的速率执行,是从上一次方法执行开始的时间算起,如果上一次方法阻塞住了,下一次也是不会执行,但是在阻塞这段时间内累计应该执行的次数,当不再阻塞时,一下子把这些全部执行掉,而后再按照固定速率继续执行。
initialDelay:如: @Scheduled(initialDelay = 10000,fixedRate = 15000
这个定时器就是在上一个的基础上加了一个initialDelay = 10000
意思就是在容器启动后,延迟10秒后再执行一次定时器,以后每15秒再执行一次该定时器.
cron表达式可以定制化执行任务,但是执行的方式是与fixedDelay相近的,也是会按照上一次方法结束时间开始算起。
如果有多个定时任务,每个任务需要在不同的线程间处理的话,就要用另外的配置:如下:
/**
- 配置多个schedule的线程配置
*/
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer{
/*
* 并行任务
*/
public void configureTasks(ScheduledTaskRegistrar taskRegistrar)
{
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setThreadNamePrefix("Schedule-Task-");
taskScheduler.setPoolSize(5);
taskScheduler.setAwaitTerminationSeconds(60);
taskScheduler.setWaitForTasksToCompleteOnShutdown(true);
taskScheduler.initialize();
taskRegistrar.setTaskScheduler(taskScheduler);
}
}
业务如下:
@Scheduled(cron = "*/5 * * * * ?")
public void test1(){
SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss");
try {
logger.info("当前线程为:"+Thread.currentThread().getName()+",方法开始时间为:"+format.format(new Date()));
Thread.sleep(10000);
logger.info("当前线程为:"+Thread.currentThread().getName()+",方法结束时间为:"+format.format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Scheduled(cron = "*/5 * * * * ?")
public void test2(){
SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss");
try {
logger.info("当前线程为:"+Thread.currentThread().getName()+",方法开始时间为:"+format.format(new Date()));
Thread.sleep(10000);
logger.info("当前线程为:"+Thread.currentThread().getName()+",方法结束时间为:"+format.format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}