Backend Development 9 min read

Single-Node and Distributed Scheduled Tasks in Java: JDK, Spring, Redis, and Middleware Solutions

This article explains how to implement single-node scheduled tasks using JDK's ScheduledExecutorService and Spring @Scheduled, compares Redis‑based approaches with ZSet and key‑space notifications, and reviews popular distributed scheduling frameworks such as Quartz, elastic‑job‑lite, LTS, and XXL‑Job for microservice environments.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Single-Node and Distributed Scheduled Tasks in Java: JDK, Spring, Redis, and Middleware Solutions

Single-Node Scheduled Tasks

JDK Native

Since JDK 1.5, ScheduledExecutorService replaces TimerTask for reliable timing. The following example creates a thread pool of 10 workers and schedules a task to start after 10 seconds and repeat every 30 seconds.

public class SomeScheduledExecutorService {
    public static void main(String[] args) {
        // Create a task queue with 10 threads
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
        // Execute task: start after 10 seconds, then every 30 seconds
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            System.out.println("执行任务:" + new Date());
        }, 10, 30, TimeUnit.SECONDS);
    }
}

Spring Task

Spring Framework provides built‑in scheduling with @Scheduled and cron expressions. A simple job class can be written as:

@Configuration
@EnableScheduling
public class SomeJob {
    private static final Logger LOGGER = LoggerFactory.getLogger(SomeJob.class);
    /**
     * Executes every minute (e.g., 18:01:00, 18:02:00)
     */
    @Scheduled(cron = "0 0/1 * * * ? *")
    public void someTask() {
        // ... task logic ...
    }
}

While single-node scheduling works for small services, distributed scenarios require more robust solutions.

Redis‑Based Implementation

Using Redis ZSet, tasks are stored with their execution timestamps as scores. A scheduled worker queries the ZSet for tasks whose score is less than the current epoch second, executes them, and then removes the processed entries.

/**
 * Description: Redis ZSet based delayed task
 */
@Configuration
@EnableScheduling
public class RedisJob {
    public static final String JOB_KEY = "redis.job.task";
    private static final Logger LOGGER = LoggerFactory.getLogger(RedisJob.class);
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public void addTask(String task, Instant instant) {
        stringRedisTemplate.opsForZSet().add(JOB_KEY, task, instant.getEpochSecond());
    }

    @Scheduled(cron = "0 0/1 * * * ? *")
    public void doDelayQueue() {
        long nowSecond = Instant.now().getEpochSecond();
        Set
strings = stringRedisTemplate.opsForZSet().range(JOB_KEY, 0, nowSecond);
        for (String task : strings) {
            LOGGER.info("执行任务:{}", task);
        }
        stringRedisTemplate.opsForZSet().remove(JOB_KEY, 0, nowSecond);
    }
}

Typical use cases include automatically canceling unpaid orders after 15 minutes or returning unclaimed red packets after 24 hours. Advantages are higher performance than MySQL and resilience to node failures.

Key‑Space Notification Method

Redis can publish expiration events when a key's TTL reaches zero. By enabling config set notify-keyspace-events Ex , a listener can react to these events and trigger the corresponding task.

/**
 * Custom listener for key expiration events
 */
public class KeyExpiredListener extends KeyExpirationEventMessageListener {
    public KeyExpiredListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String channel = new String(message.getChannel(), StandardCharsets.UTF_8);
        String key = new String(message.getBody(), StandardCharsets.UTF_8);
        // TODO: handle expired key
    }
}
@Configuration
public class RedisExJob {
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;
    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer() {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        return container;
    }
    @Bean
    public KeyExpiredListener keyExpiredListener() {
        return new KeyExpiredListener(redisMessageListenerContainer());
    }
}

Key‑space notifications are passive, consume less CPU, but lack ACK guarantees.

Distributed Scheduled Task Frameworks

Introducing Middleware Components

Separating scheduling into its own service prevents duplicate execution and simplifies scaling.

Quartz

Relies on MySQL, supports multi‑node deployment via database lock competition. No built‑in UI, configuration can be cumbersome.

elastic‑job‑lite

Uses Zookeeper for registration and discovery, enabling dynamic server addition. Provides multiple job modes, failover, status collection, and a graphical management console.

LTS

Also Zookeeper‑based, offers job logging, SPI extensions, fault‑tolerance, node monitoring, and a UI.

xxl‑job

Chinese open‑source solution built on MySQL, uses DB lock competition, supports elastic scaling, job sharding, real‑time logs, GLUE code editing, dependency management, encryption, email alerts, and internationalization.

Conclusion

In microservice architectures, using a dedicated scheduling component such as XXL‑Job is recommended for reliable task management. For small services, Spring Task remains the simplest choice, while JDK native scheduling is suitable for quick prototypes. Regardless of the approach, ensure tasks are idempotent, handle exceptions, avoid backlog, and execute at the intended time.

distributed systemsJavabackend developmentRedisSpringscheduled tasks
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.