@Scheduled注解的定时任务默认都在一个线程中执行,这个可以自己试验下或者拿我下边的案例
@Scheduled 异步运行定时任务的三个配置方式(可选)
配置1,使用自定义线程池的框架ThreadPoolTaskScheduler
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
/**
* @author ggbbk
* @date 2021/6/22
*/
@Configuration
public class ScheduleConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10);
return scheduler;
}
}
配置2,使用线程池工具类Executors
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executors;
/**
* @author ggbbk
* @date 2021/6/22
*/
@Configuration
public class XhsSchedulingConfigurer implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
}
}
测试案例(定时器每三分钟执行一次):
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @author ggbbk
* @date 2021/6/22
*/
@Component
public class TestQuartz extends Thread{
@Scheduled(cron = "00 */4 00-23 * * ?")
public void test01(){
System.out.println("test01开始运行!" + new Date());
Thread thread = new Thread(new TestQuartz());
thread.start();
try {
sleep(3000L);
System.out.println("test01结束运行!" + new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Scheduled(cron = "00 */4 00-23 * * ?")
public void test02(){
System.out.println("test02开始运行!" + new Date());
Thread thread = new Thread(new TestQuartz());
thread.start();
try {
sleep(3000L);
System.out.println("test02结束运行!" + new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Scheduled(cron = "00 */4 00-23 * * ?")
public void test03(){
System.out.println("test03开始运行!" + new Date());
Thread thread = new Thread(new TestQuartz());
thread.start();
try {
sleep(3000L);
System.out.println("test03结束运行!" + new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
}
}
测试结果
3,使用@Async
使用@Async无疑是最方便的了,它里边有一个默认的线程池,当然开发的时候为了避免OOM问题的产生都会按照自己产品的需求设计合适的线程池,这里给出一种设置线程池的例子:
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.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @author ggbbk
* @date 2021/6/23
*/
@Configuration
public class ExecutorConfig implements AsyncConfigurer {
@Bean("asyncPool")
public Executor asyncPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
/** Set the ThreadPoolExecutor's core pool size. */
int corePoolSize = 10;
executor.setCorePoolSize(corePoolSize);
/** Set the ThreadPoolExecutor's maximum pool size. */
int maxPoolSize = 50;
executor.setMaxPoolSize(maxPoolSize);
/** Set the capacity for the ThreadPoolExecutor's BlockingQueue. */
int queueCapacity = 200;
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix("Executor-");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
对应的@Async需指定上线程池
看到一位大佬的帖子是写在配置文件可以参考
链接: link.