Backend Development 10 min read

Implementing Scheduled Tasks with SpringBoot ThreadPoolTaskScheduler

This article demonstrates how to store, create, update, and delete scheduled tasks in a SpringBoot application by leveraging ThreadPoolTaskScheduler, covering task configuration, utility classes, Cron expressions, and practical testing with full code examples.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Implementing Scheduled Tasks with SpringBoot ThreadPoolTaskScheduler

To manage scheduled tasks in a SpringBoot project, the author stores task definitions in a database and provides a UI for toggling and updating task schedules. The solution relies on SpringBoot's built-in ThreadPoolTaskScheduler class.

The ThreadPoolTaskScheduler offers a schedule(Runnable task, Trigger trigger) method that creates a ScheduledFuture , which can later be cancelled via cancel(boolean mayInterruptIfRunning) . The article shows the relevant source code of this method.

public ScheduledFuture
schedule(Runnable task, Trigger trigger) {
    ScheduledExecutorService executor = getScheduledExecutor();
    try {
        ErrorHandler errorHandler = this.errorHandler;
        if (errorHandler == null) {
            errorHandler = TaskUtils.getDefaultErrorHandler(true);
        }
        return new ReschedulingRunnable(task, trigger, executor, errorHandler).schedule();
    } catch (RejectedExecutionException ex) {
        throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
    }
}

A configuration class SchedulingTaskConfig defines a bean named taskSchedulerPool that configures the thread pool size, thread name prefix, shutdown behavior, and await termination settings.

@Configuration
public class SchedulingTaskConfig {
    @Bean(name = "taskSchedulerPool")
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(60);
        taskScheduler.setThreadNamePrefix("task-pool-");
        taskScheduler.setAwaitTerminationSeconds(3000);
        taskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        return taskScheduler;
    }
}

A utility class SpringContextUtils implements ApplicationContextAware to retrieve beans by name at runtime, enabling dynamic method invocation.

@Component
public class SpringContextUtils implements ApplicationContextAware {
    private static ApplicationContext context;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextUtils.context = applicationContext;
    }
    public static Object getBean(String name) {
        return context.getBean(name);
    }
}

The core runnable SchedulingTaskRunnable<T> receives generic parameters, the target class name, and method name, then uses reflection to invoke the specified method with or without arguments.

public class SchedulingTaskRunnable
implements Runnable {
    private final T t;
    private final String clazz;
    private final String methodName;
    SchedulingTaskRunnable(T t, String clazz, String methodName) { ... }
    @Override
    public void run() {
        Object bean = SpringContextUtils.getBean(clazz);
        Method method = Objects.nonNull(t) ? bean.getClass().getDeclaredMethod(methodName, t.getClass())
                                          : bean.getClass().getDeclaredMethod(methodName);
        ReflectionUtils.makeAccessible(method);
        if (Objects.nonNull(t)) {
            method.invoke(bean, t);
        } else {
            method.invoke(bean);
        }
    }
}

A management component SchedulingTaskManage keeps a ConcurrentHashMap<String, ScheduledFuture<?>> to store and control tasks. It provides createSchedulingTask and stopSchedulingTask methods that schedule a task with a Cron expression and cancel it when needed.

@Component
public class SchedulingTaskManage {
    private final ConcurrentHashMap
> cache = new ConcurrentHashMap<>();
    @Resource(name = "taskSchedulerPool")
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;
    public void createSchedulingTask(String key, SchedulingTaskRunnable
runnable, String cron) {
        ScheduledFuture
schedule = threadPoolTaskScheduler.schedule(runnable, new CronTrigger(cron));
        cache.put(key, schedule);
    }
    public void stopSchedulingTask(String key) {
        ScheduledFuture
future = cache.get(key);
        if (future != null) {
            future.cancel(true);
            cache.remove(key);
        }
    }
}

The article also shows how to create the database table t_schedule_task to persist task metadata, and provides a test service that adds, edits, and deletes tasks while validating Cron expressions.

create table t_schedule_task(
    id int auto_increment primary key,
    task_clazz varchar(200) not null,
    task_method varchar(200) not null,
    cron varchar(200) not null,
    status smallint default 0 comment '0: enabled, 1: disabled'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 comment 'Scheduled task management table';

Running the example demonstrates that a task executes every 5 seconds, logs the user information, and can be cleanly removed, after which no further executions occur.

In summary, ThreadPoolTaskScheduler manages scheduled tasks by creating and cancelling threads; using reflection allows dynamic method binding, and the provided utilities make task lifecycle management straightforward in a SpringBoot backend.

BackendJavaSpringBootcronScheduledTaskThreadPoolTaskScheduler
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.