org.jgroups.util.ExpiryCache Maven / Gradle / Ivy
package org.jgroups.util;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
/** Cache which maintains timestamps for keys, and methods to remove/replace expired keys. Compared to {@link AgeOutCache},
* ExpiryCache doesn't require a timer task to run
* @author Bela Ban
* @version 3.3
*/
public class ExpiryCache {
protected long timeout; // in nanoseconds
// Maintains keys and timestamps (in nanoseconds)
protected final ConcurrentMap map=new ConcurrentHashMap();
/**
* Creates a new instance
* @param timeout Timeout in ms
*/
public ExpiryCache(long timeout) {
setTimeout(timeout);
}
public long getTimeout() {return TimeUnit.MILLISECONDS.convert(timeout, TimeUnit.NANOSECONDS);}
public void setTimeout(long timeout) {this.timeout=TimeUnit.NANOSECONDS.convert(timeout, TimeUnit.MILLISECONDS);}
public boolean addIfAbsentOrExpired(K key) {
Long val=map.get(key);
if(val == null)
return map.putIfAbsent(key, System.nanoTime()) == null;
long current_time=System.nanoTime();
return hasExpired(val, current_time) && map.replace(key, val, current_time);
}
public boolean contains(K key) {
return key != null && map.containsKey(key);
}
public boolean hasExpired(K key) {
Long val=map.get(key);
return val == null || hasExpired(val, System.nanoTime());
}
public void remove(K key) {
map.remove(key);
}
public void removeAll(Collection keys) {
map.keySet().removeAll(keys);
}
public int removeExpiredElements() {
int removed=0;
long current_time=System.nanoTime();
for(Map.Entry entry: map.entrySet()) {
Long val=entry.getValue();
if(val == null || hasExpired(val, current_time)) {
map.remove(entry.getKey());
removed++;
}
}
return removed;
}
public void clear() {
map.clear();
}
public int size() {
return map.size();
}
public String toString() {
StringBuilder sb=new StringBuilder();
long current_time=System.nanoTime();
for(Map.Entry entry: map.entrySet()) {
sb.append(entry.getKey()).append(": (age: ");
long val=entry.getValue(); // timestamp in ns
long age=TimeUnit.MILLISECONDS.convert(current_time - val, TimeUnit.NANOSECONDS); // ms
if(age< 1000L)
sb.append(age).append(" ms)");
else
sb.append(TimeUnit.SECONDS.convert(age, TimeUnit.MILLISECONDS)).append(" secs");
sb.append("\n");
}
return sb.toString();
}
protected boolean hasExpired(long val, long current_time) {
return current_time - val > timeout;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy