How to Implement Precise Delays in Java Backend Using Timer and Redis
This article explores various strategies for controlling execution timing in Java backend services, comparing Thread.sleep, Timer, and Redis-based expiration techniques, and provides practical code examples and configuration steps for integrating Redis with Spring Boot to achieve reliable delayed processing.
Introduction
When integrating with third‑party services, a token may become invalid after a short period, and a scheduled task that fetches a new token can sometimes run while the token is still being refreshed, causing occasional failures. This article discusses how to delay a request by a short interval (e.g., 800 ms) to avoid such race conditions.
1. Time‑control solutions
1.1 Thread.sleep
The simplest approach is Thread.sleep(800), but in a multithreaded environment an interrupt can cause an exception and suspend the thread, which is not elegant and violates design principles.
1.2 Using java.util.Timer
Java provides a Timer class that can schedule a task after a specified delay. The following example shows a minimal timer implementation:
public class TimmerTest {
/** Test method */
public void test() {
Timer timer = new Timer();
timer.schedule(new MyTask(), 800);
}
public class MyTask extends TimerTask {
/** Run method */
@Override
public void run() {
System.out.println("输出");
}
}
}This method requires creating a separate TimerTask class, which increases code intrusion and is therefore not ideal.
1.3 Redis‑based delay
Redis offers the EXPIRE command to set a key’s lifetime. By storing a placeholder key with a short TTL, we can achieve a non‑intrusive delay. The advantages are low code intrusion, flexibility through key‑based identifiers, and minimal implementation effort.
2. Redis integration in Spring Boot
2.1 Maven dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>2.2 Redis configuration
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Autowired
private RedisTemplate redisTemplate;
@Bean
public RedisTemplate redisTemplateInit() {
// key serializer
redisTemplate.setKeySerializer(new StringRedisSerializer());
// value serializer
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
}2.3 Redis utility class
@Component
public class RedisManager {
private static final Logger LOGGER = LoggerFactory.getLogger(RedisManager.class);
@Autowired
private RedisTemplate redisTemplate;
@SuppressWarnings("unchecked")
public <T> ValueOperations<String, T> setObject(final String key, final T value) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
operation.set(key, value);
return operation;
}
@SuppressWarnings("unchecked")
public <T> ValueOperations<String, T> setObject(final String key, final T value, final long time) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
operation.set(key, value, time, TimeUnit.SECONDS);
return operation;
}
@SuppressWarnings("unchecked")
public <T> ValueOperations<String, T> setObjectForMillSeconds(final String key, final T value, final long time) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
operation.set(key, value, time, TimeUnit.MILLISECONDS);
return operation;
}
@SuppressWarnings("unchecked")
public Object getObject(final String key) {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
if (valueOperations == null || !redisTemplate.hasKey(key)) {
return null;
}
return valueOperations.get(key);
}
@SuppressWarnings("unchecked")
public String getString(final String key) {
String value = "";
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
if (valueOperations != null && redisTemplate.hasKey(key)) {
Object object = valueOperations.get(key);
if (object != null) {
LOGGER.info("--getString--object not empty");
value = object.toString();
} else {
LOGGER.info("--getString--object empty");
}
}
return value;
}
}2.4 Using Redis for time control
import com.youjia.orders.redis.RedisManager;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Objects;
public class RedisTest extends OrderProviderApplicationTests {
@Autowired
private RedisManager redisManager;
@Test
public void test() {
controlTime("10000001", 10L);
}
public void controlTime(String requestId, Long timeOut) {
if (Objects.isNull(requestId) || Objects.isNull(timeOut)) {
return;
}
final String value = "value";
redisManager.setObject(requestId, value, timeOut);
final long startTime = System.currentTimeMillis();
System.out.println("开始控制时间");
for (;;) {
if (Objects.isNull(redisManager.getObject(requestId))) {
break;
}
}
final long endTime = System.currentTimeMillis();
final long useTime = endTime - startTime;
System.out.println("一共耗费时间:" + useTime);
}
}3. Conclusion
The article demonstrates common timing‑control challenges in backend development and shows how to solve them elegantly by leveraging middleware such as Redis or built‑in Java utilities, thereby reducing code intrusion and improving reliability.
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.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
