Scheduling 本身是单线程机制,要想多个定时任务并行执行,需要使用 @Async 注解采用异步执行方式。在Spring中,基于@Async标注的方法,称之为异步方法,这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。
- 启动类添加@EnableScheduling开启定时任务,添加@EnableAsync开启异步支持
@SpringBootApplication
@EnableWebMvc
@EnableAsync
@EnableScheduling
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class RiverownerservicewzApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(RiverownerservicewzApplication.class, args);
}
}
- 创建定时任务实例
/**
- @author wjw
- @version 1.0
- @date 2020-06-29 12:13
*/
@Component
public class test {
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Async
@Scheduled(cron = "0 0/1 * * * ? ")
public void test1(){
System.out.println("第一个定时任务开始:" + format.format(new Date()));
try {
Thread.sleep(10000);
System.out.println("第一个定时任务结束:" + format.format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Async
@Scheduled(cron = "0 0/1 * * * ? ")
public void test2(){
System.out.println("第二个定时任务开始:" + format.format(new Date()));
try {
Thread.sleep(10000);
System.out.println("第二个定时任务结束:" + format.format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 执行结果
第二个定时任务开始:2020-06-29 13:47:00
第一个定时任务开始:2020-06-29 13:47:00
第一个定时任务结束:2020-06-29 13:47:10
第二个定时任务结束:2020-06-29 13:47:10
Async 在未指定线程池时,使用的是springBoot内置的线程池,那如何指定使用自定义的线程池呢?下面是配置Async异步执行使用自定义线程池的步骤。
- 自定义线程池
/**
* @author wjw
* @version 1.0
* @date 2020-03-02 10:47
*/
@Configuration
@EnableAsync
public class ExecutorConfig {
private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);
@Bean(name = "MyThreadPool")
public Executor MyThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(30);//表示线程池核心线程,正常情况下开启的线程数量。
executor.setQueueCapacity(500); //配置队列大小
executor.setMaxPoolSize(50);//当核心线程都在跑任务,还有多余的任务会存到此处。
executor.setKeepAliveSeconds(60);//非核心线程的超时时长,超长后会被回收。
executor.setThreadNamePrefix("MyThreadPool-");//配置线程池前缀
executor.setWaitForTasksToCompleteOnShutdown(true);//用来设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
executor.setRejectedExecutionHandler((Runnable r, ThreadPoolExecutor exe) -> {
logger.warn("MyThreadPool-当前任务线程池队列已满!");
});//配置拒绝策略
executor.initialize();//初始化线程池。
return executor;
}
}
- 创建定时任务示例,只需在Async注解后指定线程池名即可
@Async("MyThreadPool")
@Scheduled(cron = "0 0/1 * * * ? ")
public void test1(){
System.out.println("第一个定时任务开始:" + format.format(new Date()));
try {
Thread.sleep(10000);
System.out.println("第一个定时任务结束:" + format.format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}