- 有些任务需要服务启动后立即执行,比如,加载一些数据到内存。可以通过 jakarta.annotation.PostConstruct 注解实现。
建一个 PostConstructService , 在某个方法上加上 注解 PostConstruct
@Service
public class PostConstructService {
Logger logger = LoggerFactory.getLogger(getClass());
@PostConstruct
public void taskAfterStartup() {
logger.info("run task after startup");
}
}
启动服务 mvn clean spring-boot:run , 可以看到服务启动后在终端打印出 log , "run task after startup"
注意: 这里 log 是由主线程 main 打出的,如果执行任务时间太长,会影响服务启动。 可以使用异步任务,来执行服务启动后的一些初始化操作。
- 在 SpringBoot 的启动类, 加上注解 org.springframework.scheduling.annotation.EnableAsync , 支持异步任务。
@EnableAsync
@SpringBootApplication
public class MarsApplication {
...
}
配置异步任务的 thread pool , 建一个 ThreadPoolConfig 配置类
@Configuration
public class ThreadPoolConfig {
@Value("${spring.application.name:}")
String name;
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
String namePrefix = String.format("%s_task_", name);
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(8);
executor.setMaxPoolSize(16);
executor.setQueueCapacity(8);
executor.setThreadNamePrefix(namePrefix);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setKeepAliveSeconds(60);
executor.initialize();
return executor;
}
}
在 PostConstructService 中定义一个 asyncTask() 任务, 服务启动后执行异步任务 asyncTask() 不会影响服务启动时间。
@Service
public class PostConstructService {
Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
ThreadPoolTaskExecutor executor;
@PostConstruct
public void taskAfterStartup() {
logger.info("run task after startup");
asyncTask();
}
public void asyncTask() {
FutureTask<String> task = new FutureTask<>(
() -> {
logger.info("it's a async task");
return "done";
}
);
executor.execute(task);
}
}
可以看到 log "it's a async task" 是由线程 mars_task_1 执行的。
- 在服务中执行定时任务 (有些类似 cron job) 。
首先配置定时任务的线程池,在 ThreadPoolConfig 中
@Configuration
public class ThreadPoolConfig {
...
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
String namePrefix = String.format("%s_scheduler_", name);
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix(namePrefix);
scheduler.setPoolSize(5);
scheduler.initialize();
return scheduler;
}
}
其次, 在启动类中添加注解 org.springframework.scheduling.annotation.EnableScheduling
@EnableScheduling
@EnableAsync
@SpringBootApplication
public class MarsApplication {
public static void main(String[] args) {
SpringApplication.run(MarsApplication.class, args);
}
}
然后, 建一个 ScheduleTaskService
// 使用注解 @Component
@Component
public class ScheduleTaskService {
Logger logger = LoggerFactory.getLogger(getClass());
// 每 10 打印一次 log
@Scheduled(cron = "*/10 * * * * ?")
private void schedulePrintLog() {
long current = System.currentTimeMillis();
logger.info("scheduling print log, current [{}]", current);
}
}
本节的代码 gitee.com/yren/mars/t…
语雀上的副本 www.yuque.com/u2177997/sr…