本文目录导读:

在Java中实现TTL(Time-To-Live,生存时间)功能通常用于缓存、验证码、会话管理等场景,以下是几种常见的实现方式及完整案例:
基于HashMap + 定时器实现简单TTL缓存
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class SimpleTTLCache<K, V> {
private final Map<K, CacheEntry<V>> cache = new HashMap<>();
private final ScheduledExecutorService cleanupExecutor =
Executors.newSingleThreadScheduledExecutor();
// 定期清理过期条目
public SimpleTTLCache() {
cleanupExecutor.scheduleAtFixedRate(this::cleanupExpiredEntries,
1, 1, TimeUnit.SECONDS);
}
private static class CacheEntry<V> {
private final V value;
private final long expiryTime;
public CacheEntry(V value, long expiryTime) {
this.value = value;
this.expiryTime = expiryTime;
}
public boolean isExpired() {
return System.currentTimeMillis() > expiryTime;
}
}
public void put(K key, V value, long ttlMillis) {
long expiryTime = System.currentTimeMillis() + ttlMillis;
cache.put(key, new CacheEntry<>(value, expiryTime));
}
public V get(K key) {
CacheEntry<V> entry = cache.get(key);
if (entry != null && !entry.isExpired()) {
return entry.value;
}
cache.remove(key);
return null;
}
private void cleanupExpiredEntries() {
cache.entrySet().removeIf(entry -> entry.getValue().isExpired());
}
}
使用ConcurrentHashMap实现线程安全版本
import java.util.concurrent.ConcurrentHashMap;
public class ThreadSafeTTLCache<K, V> {
private final ConcurrentHashMap<K, Entry<V>> cache = new ConcurrentHashMap<>();
private static class Entry<V> {
private final V value;
private final long timestamp;
private final long ttlMillis;
public Entry(V value, long ttlMillis) {
this.value = value;
this.timestamp = System.currentTimeMillis();
this.ttlMillis = ttlMillis;
}
public boolean isExpired() {
return System.currentTimeMillis() - timestamp > ttlMillis;
}
}
public void put(K key, V value, long ttlMillis) {
cache.put(key, new Entry<>(value, ttlMillis));
}
public V get(K key) {
Entry<V> entry = cache.get(key);
if (entry == null) return null;
if (entry.isExpired()) {
cache.remove(key);
return null;
}
return entry.value;
}
// 获取剩余TTL
public long getRemainingTTL(K key) {
Entry<V> entry = cache.get(key);
if (entry == null) return -1;
long remaining = entry.ttlMillis -
(System.currentTimeMillis() - entry.timestamp);
return remaining > 0 ? remaining : -1;
}
public void remove(K key) {
cache.remove(key);
}
public int size() {
// 清理过期条目后再返回大小
cache.entrySet().removeIf(entry -> entry.getValue().isExpired());
return cache.size();
}
}
结合Caffeine实现高性能TTL缓存
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.TimeUnit;
public class CaffeineTTLCache {
private final Cache<String, String> cache;
public CaffeineTTLCache() {
cache = Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(5, TimeUnit.MINUTES) // 写入后5分钟过期
.expireAfterAccess(2, TimeUnit.MINUTES) // 访问后2分钟过期
.recordStats()
.build();
}
public void put(String key, String value) {
cache.put(key, value);
}
public String get(String key) {
return cache.getIfPresent(key);
}
public void invalidate(String key) {
cache.invalidate(key);
}
}
Redis实现分布式TTL
import redis.clients.jedis.Jedis;
public class RedisTTLService {
private Jedis jedis;
public RedisTTLService(String host, int port) {
jedis = new Jedis(host, port);
}
// 设置带TTL的键值
public void setWithTTL(String key, String value, int ttlSeconds) {
jedis.setex(key, ttlSeconds, value);
}
// 获取值(Redis会自动删除过期的键)
public String get(String key) {
return jedis.get(key);
}
// 查看剩余TTL(-2表示键不存在,-1表示永不过期)
public long getTTL(String key) {
return jedis.ttl(key);
}
// 更新TTL
public void updateTTL(String key, int ttlSeconds) {
jedis.expire(key, ttlSeconds);
}
}
完整使用示例
public class TTLDemo {
public static void main(String[] args) throws InterruptedException {
// 演示简单TTL缓存
SimpleTTLCache<String, String> cache = new SimpleTTLCache<>();
// 设置2秒后过期
cache.put("user:1", "张三", 2000);
System.out.println("第一次获取: " + cache.get("user:1")); // 张三
Thread.sleep(2500); // 等待2.5秒
System.out.println("过期后获取: " + cache.get("user:1")); // null
// 演示线程安全版本
ThreadSafeTTLCache<String, Integer> safeCache = new ThreadSafeTTLCache<>();
safeCache.put("count", 100, 1000); // 1秒过期
System.out.println("剩余TTL: " + safeCache.getRemainingTTL("count"));
System.out.println("值: " + safeCache.get("count")); // 100
// 使用Caffeine(需引入依赖)
// CaffeineTTLCache caffeineCache = new CaffeineTTLCache();
// caffeineCache.put("session", "active");
// System.out.println(caffeineCache.get("session"));
}
}
使用建议
| 场景 | 推荐方案 |
|---|---|
| 简单单机应用 | HashMap + 定时清理 |
| 高并发单机应用 | ConcurrentHashMap 或 Caffeine |
| 分布式应用 | Redis、Memcached |
| 微服务架构 | 分布式缓存(Redis) |
注意事项:
- 定期清理时注意性能影响
- 使用滑过时间(sliding expiration)还是固定时间(fixed expiration)
- 考虑内存泄漏问题
- 分布式环境下需要考虑缓存一致性
您可以根据具体业务场景选择合适的TTL实现方案。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播