基于DelayQueue实现的带失效时间的缓存

时间:2022-07-24
本文章向大家介绍基于DelayQueue实现的带失效时间的缓存,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
import java.util.concurrent.DelayQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Auther: ZhangShenao
 * @Date: 2019/2/27 18:38
 * @Description:缓存实现,可自动移除过期的缓存项
 */
public class ScheduledCache<K, V> {
    private final DelayQueue<CacheItem<K, V>> cache = new DelayQueue<>();

    private final int capacity;

    private AtomicInteger size;

    private volatile boolean valid;

    public ScheduledCache(int capacity) {
        this.capacity = capacity;
        size = new AtomicInteger(0);
        valid = true;
        startCheckTask();
    }

    public void put(K key, V value, long timeout) {
        CacheItem item = new CacheItem();
        item.setKey(key);
        item.setValue(value);
        item.setExpireTimeMillis(System.currentTimeMillis() + timeout);
        cache.put(item);
        size.incrementAndGet();
        System.err.println(String.format("添加缓存项。key: %s, value: %s。", item.getKey(), item.getValue()));
    }

    public void evict(){
        size.compareAndSet(size.get(),0);
        valid = false;
        cache.clear();
    }

    private class CheckExpiredItemTask implements Runnable {
        @Override
        public void run() {
            while (valid) {
                try {
                    expire(cache.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void startCheckTask(){
        new Thread(new CheckExpiredItemTask()).start();
    }

    private void expire(CacheItem item) {
        size.decrementAndGet();
        System.err.println(String.format("缓存项已过期!key: %s, value: %s, 缓存剩余项数量: %s。", item.getKey(), item.getValue(), size.get()));
    }
}
import lombok.Getter;
import lombok.Setter;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: ZhangShenao
 * @Date: 2019/2/27 18:34
 * @Description:缓存项
 */
@Getter
@Setter
public class CacheItem<K,V> implements Delayed{
    private K key;
    private V value;
    private long expireTimeMillis;

    @Override
    public long getDelay(TimeUnit unit) {
        return expireTimeMillis - System.currentTimeMillis();
    }

    @Override
    public int compareTo(Delayed o) {
        CacheItem item = (CacheItem)o;
        return (expireTimeMillis > item.expireTimeMillis ? 1 : 0);
    }
}