Implementing Fixed-Time Scheduled Tasks in Single-Node and Distributed Java Applications
This article explains how to implement fixed‑time scheduled tasks on a single machine using Timer and ScheduledThreadPoolExecutor, how to build a custom Redis‑based distributed scheduler with distributed locks, and compares several third‑party frameworks such as Quartz, TBSchedule, Elastic‑Job and Sature for distributed task execution.
1. Single‑machine fixed‑time scheduled task implementation
1.1 Timer execution mechanism
Describes the basic principle of Java Timer, which operates on absolute time and runs in a single thread.
1.2 ScheduledThreadPoolExecutor mechanism
Explains the working principle of ScheduledThreadPoolExecutor, which uses relative time, supports multiple threads, and catches task exceptions.
Key differences:
Timer uses absolute time; ScheduledThreadPoolExecutor uses relative time.
Timer is single‑threaded; ScheduledThreadPoolExecutor is multi‑threaded.
Timer thread crashes on exception; ScheduledThreadPoolExecutor handles exceptions internally.
1.3 Custom implementation of fixed‑time tasks
Create a database table to store scheduled tasks and business IDs.
Define a Producer class that writes tasks with a target timestamp into a delay queue.
Define a Consumer interface for business logic to consume queued tasks.
Implement a Spring Boot auto‑start method that continuously polls the delay queue, compares timestamps, executes due tasks, and sleeps 100 ms between iterations.
1.4 Quartz implementation
Reference documentation: Quartz Docs
2. Distributed fixed‑time scheduled task implementation (custom Redis solution)
2.1 Design analysis
Because the application is deployed across multiple nodes, a distributed lock is required to ensure consistency.
Use Redis Sorted Set to store task IDs with their target timestamps (ZADD).
Spring Boot scheduled job runs every second to trigger the consumer method.
The consumer acquires a distributed lock, fetches the smallest timestamp from the sorted set, compares it with the current time, executes if due, otherwise sleeps 100 ms before the next loop.
/**
* Obtain distributed lock
* @param redisClientId Redis client ID
* @return boolean
*/
public boolean redisDistributedLock(String key, String redisClientId, long timeout, TimeUnit unit) {
ValueOperations<String, String> ops = redisTemplate.opsForValue();
if (ops.setIfAbsent(key, redisClientId, timeout, unit)) {
return true;
}
String cacheClientId = ops.get(key);
if (cacheClientId.equals(redisClientId)) {
redisExpire(key, timeout, unit);
return true;
}
return false;
} /**
* Execute scheduled task
*/
public void runBenchGameDelayTask(BenchDelayTaskType type) {
while (true) {
Set<ZSetOperations.TypedTuple<String>> typedTuples = benchGameCacheService.benchGameTaskZRange(type);
if (typedTuples.size() > 0) {
benchGameTaskProcess(type, typedTuples);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
log.error("[runBenchGameDelayTask] type={}, error={}", type.getData(), e);
}
}
}3. Distributed fixed‑time scheduled task implementations using third‑party frameworks
3.1 Quartz cluster solution
Quartz uses a scheduler_locks table and pessimistic row locking on the triggers table to ensure that only one node executes a job at a time. The clustering relies on database locks, providing high availability but not task sharding.
3.2 TBSchedule
TBSchedule is a high‑performance distributed scheduler used by major Chinese internet companies. It supports task sharding via ZooKeeper and provides a web console for monitoring and managing jobs.
3.3 Elastic‑Job
Elastic‑Job offers lightweight, center‑less distributed scheduling with features such as elastic scaling, failover, missed‑execution re‑trigger, consistent sharding, self‑diagnosis, parallel scheduling, and rich job types.
3.4 Vipshop open‑source framework Sature
Sature provides time‑based, language‑agnostic jobs, web‑based management, sub‑task sharding, second‑level scheduling, intelligent load‑based allocation, fail detection & failover, monitoring, multi‑active cluster deployment, container friendliness, and can handle billions of schedules per day.
Thank you for reading, hope it helps :)
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
