寻求支持键值对过期后执行清理操作的哈希映射实现方案
实现带过期后自动清理逻辑的键值映射结构
方案一:基于Guava的RemovalListener实现
Guava的CacheBuilder(替代旧版MapMaker)支持移除监听器,当键值对因过期、手动移除或内存回收被清理时,会触发监听器逻辑,刚好可以用来执行连接关闭操作。
示例代码:
import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.RemovalListener; import com.google.common.cache.RemovalNotification; import java.util.concurrent.TimeUnit; public class ExpiringConnectionCache { private final Cache<String, Connection> connectionCache; public ExpiringConnectionCache() { RemovalListener<String, Connection> removalListener = notification -> { Connection conn = notification.getValue(); if (conn != null && !conn.isClosed()) { // 执行连接关闭逻辑 conn.close(); } }; connectionCache = CacheBuilder.newBuilder() .expireAfterAccess(30, TimeUnit.MINUTES) // 或按写入时间过期expireAfterWrite .removalListener(removalListener) .build(); } public void putConnection(String key, Connection conn) { connectionCache.put(key, conn); } public Connection getConnection(String key) { return connectionCache.getIfPresent(key); } }
方案二:自定义基于ScheduledExecutorService的过期映射
如果不想依赖第三方库,可以自行实现轻量版本,用线程安全的哈希表存储键值对,配合定时任务扫描并清理过期条目。
示例代码:
import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class CustomExpiringMap<K, V> { private final Map<K, ExpiringEntry<V>> map = new ConcurrentHashMap<>(); private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); public CustomExpiringMap(long checkInterval, TimeUnit unit) { // 定期扫描清理过期条目 scheduler.scheduleAtFixedRate(this::cleanupExpiredEntries, checkInterval, checkInterval, unit); } public void put(K key, V value, long expireTime, TimeUnit unit) { long expireTimestamp = System.currentTimeMillis() + unit.toMillis(expireTime); map.put(key, new ExpiringEntry<>(value, expireTimestamp)); } public V get(K key) { ExpiringEntry<V> entry = map.get(key); if (entry == null || entry.isExpired()) { map.remove(key); return null; } return entry.getValue(); } private void cleanupExpiredEntries() { map.entrySet().removeIf(entry -> { ExpiringEntry<V> valueEntry = entry.getValue(); if (valueEntry.isExpired()) { // 针对Connection类型执行关闭逻辑 if (valueEntry.getValue() instanceof Connection) { Connection conn = (Connection) valueEntry.getValue(); if (!conn.isClosed()) { conn.close(); } } return true; } return false; }); } private static class ExpiringEntry<V> { private final V value; private final long expireTimestamp; public ExpiringEntry(V value, long expireTimestamp) { this.value = value; this.expireTimestamp = expireTimestamp; } public V getValue() { return value; } public boolean isExpired() { return System.currentTimeMillis() > expireTimestamp; } } // 关闭定时任务释放资源 public void shutdown() { scheduler.shutdown(); } }
方案三:使用Caffeine缓存库
Caffeine是Guava缓存的高性能替代方案,API风格类似但性能更优,同样支持移除监听器处理过期清理逻辑。
示例代码:
import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.RemovalListener; import java.util.concurrent.TimeUnit; public class CaffeineConnectionCache { private final Cache<String, Connection> connectionCache; public CaffeineConnectionCache() { RemovalListener<String, Connection> removalListener = (key, conn, cause) -> { if (conn != null && !conn.isClosed()) { conn.close(); } }; connectionCache = Caffeine.newBuilder() .expireAfterWrite(30, TimeUnit.MINUTES) .removalListener(removalListener) .build(); } public void put(String key, Connection conn) { connectionCache.put(key, conn); } public Connection get(String key) { return connectionCache.getIfPresent(key); } }
内容的提问来源于stack exchange,提问作者user9890324
相关产品推荐
相关产品推荐

