Scheduled jobs and @Async methods
Run work on a timer or off the request thread, with pools you sized on purpose.
Open this lesson in the learning hubKey points
- Add
@EnableScheduling, then@Scheduledon a no-argument method of a bean. fixedDelaycounts from the end of the previous run;fixedRatecounts from its start and can overlap.- The scheduler pool is one thread by default - set
spring.task.scheduling.pool.sizeor one slow job stalls the rest. @Asyncplus@EnableAsyncreturns straight away and runs the body on the task executor.- An exception thrown in a
voidasync method is lost unless you register anAsyncUncaughtExceptionHandler. - Several instances means several schedulers. Use ShedLock or a database lock so a job runs once per cluster.
Example
@Configuration
@EnableScheduling
@EnableAsync
class TaskConfig { }
@Component
class Housekeeping {
@Scheduled(fixedDelay = 5000) // 5s AFTER the previous run finished
void purgeExpiredCarts() { carts.deleteExpired(); }
@Scheduled(cron = "0 15 3 * * *", zone = "Europe/Berlin") // 03:15 every day
void nightlyReport() { reports.build(); }
}
@Service
class MailService {
@Async // caller returns immediately
public CompletableFuture<Void> sendReceipt(Order order) {
mailer.send(order.customerEmail(), render(order));
return CompletableFuture.completedFuture(null);
}
}
// application.yml
// spring.task.scheduling.pool.size: 4
// spring.task.execution.pool.max-size: 16
// spring.task.execution.pool.queue-capacity: 100
Background work needs an explicit pool size and an explicit failure path, or it fails silently.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Spring Boot course, and every lesson in it is listed on the Spring Boot contents page.