很多情况下 我们对缓存数据需要有时效性 的要求,可以借助 delayQueue 完成这一工作
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class AutoCleanMap<K, V> {
private final static Integer DEFAULT_TIME=5;
private final static TimeUnit DEFAULT_TIMEUNIT=TimeUnit.SECONDS;
private long effectiveTime;
private TimeUnit timeUnit ;
private Map<K, V> map = new ConcurrentHashMap<K, V>();
private DelayQueue<Data<K>> cleanQueue = new DelayQueue<Data<K>>();
public AutoCleanMap(long effectiveTime, TimeUnit timeUnit) {
this.effectiveTime = effectiveTime;
this.timeUnit = timeUnit;
Thread thread = new Thread() {
public void run() {
for (;;)
try {
map.remove(cleanQueue.take().getKey());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.setDaemon(true);
thread.start();
}
public AutoCleanMap() {
this(DEFAULT_TIME, DEFAULT_TIMEUNIT);
}
public void put(K key, V value) {
Data<K> data = new Data<K>(key, timeUnit.toNanos(effectiveTime));
synchronized (map) {
if (map.get(key) != null) {
cleanQueue.remove(data);
}
map.put(key, value);
}
cleanQueue.add(data);
}
public V get(K k) {
return map.get(k);
}
private static class Data<K> implements Delayed {
private K key;
private long endTime;
public Data(K key, long effectiveTime) {
super();
this.key = key;
this.endTime = effectiveTime + System.nanoTime();
}
public K getKey() {
return key;
}
@Override
public int compareTo(Delayed o) {
if (!(o instanceof Data))
return 1;
if (this == o)
return 0;
@SuppressWarnings("unchecked")
Data<K> data = (Data<K>) o;
if (this.endTime == data.endTime)
return 0;
return this.endTime > data.endTime ? 1 : -1;
}
@Override
public long getDelay(TimeUnit unit) {
return endTime - System.nanoTime();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((key == null) ? 0 : key.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
@SuppressWarnings("unchecked")
Data<K> other = (Data<K>) obj;
if (key == null) {
if (other.key != null)
return false;
} else if (!key.equals(other.key))
return false;
return true;
}
}
}