만료 키가있는 Java 시간 기반 맵 / 캐시
지정된 시간 초과 후 항목을 자동으로 제거하는 Java Map 또는 유사한 표준 데이터 저장소에 대해 알고 있습니까? 이는 오래된 만료 된 항목이 자동으로 "나중 만료"되는 에이징을 의미합니다.
Maven을 통해 액세스 할 수있는 오픈 소스 라이브러리에서?
기능을 직접 구현하고 과거에 여러 번 수행 한 방법을 알고 있으므로 그 점에서 조언을 구하는 것이 아니라 좋은 참조 구현을 가리키는 포인터입니다.
WeakHashMap 과 같은 WeakReference 기반 솔루션 은 옵션이 아닙니다. 내 키는 비 인턴 문자열 일 가능성이 높으며 가비지 수집기에 의존하지 않는 구성 가능한 시간 초과가 필요하기 때문입니다.
Ehcache 는 외부 구성 파일이 필요하기 때문에 의존하고 싶지 않은 옵션이기도합니다. 코드 전용 솔루션을 찾고 있습니다.
예. Google Collections 또는 Guava 는 이제 이름을 딴 MapMaker 라는 것을 가지고 있습니다.
ConcurrentMap<Key, Graph> graphs = new MapMaker()
.concurrencyLevel(4)
.softKeys()
.weakValues()
.maximumSize(10000)
.expiration(10, TimeUnit.MINUTES)
.makeComputingMap(
new Function<Key, Graph>() {
public Graph apply(Key key) {
return createExpensiveGraph(key);
}
});
최신 정보:
구아바 10.0 (2011 년 9 월 28 일 출시)부터 이러한 많은 MapMaker 메소드는 새로운 CacheBuilder 를 위해 더 이상 사용되지 않습니다 .
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(10000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(
new CacheLoader<Key, Graph>() {
public Graph load(Key key) throws AnyException {
return createExpensiveGraph(key);
}
});
이것은 동일한 요구 사항과 동시성에 대해 수행 한 샘플 구현입니다. 누군가에게 유용 할 수 있습니다.
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
*
* @author Vivekananthan M
*
* @param <K>
* @param <V>
*/
public class WeakConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {
private static final long serialVersionUID = 1L;
private Map<K, Long> timeMap = new ConcurrentHashMap<K, Long>();
private long expiryInMillis = 1000;
private static final SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss:SSS");
public WeakConcurrentHashMap() {
initialize();
}
public WeakConcurrentHashMap(long expiryInMillis) {
this.expiryInMillis = expiryInMillis;
initialize();
}
void initialize() {
new CleanerThread().start();
}
@Override
public V put(K key, V value) {
Date date = new Date();
timeMap.put(key, date.getTime());
System.out.println("Inserting : " + sdf.format(date) + " : " + key + " : " + value);
V returnVal = super.put(key, value);
return returnVal;
}
@Override
public void putAll(Map<? extends K, ? extends V> m) {
for (K key : m.keySet()) {
put(key, m.get(key));
}
}
@Override
public V putIfAbsent(K key, V value) {
if (!containsKey(key))
return put(key, value);
else
return get(key);
}
class CleanerThread extends Thread {
@Override
public void run() {
System.out.println("Initiating Cleaner Thread..");
while (true) {
cleanMap();
try {
Thread.sleep(expiryInMillis / 2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void cleanMap() {
long currentTime = new Date().getTime();
for (K key : timeMap.keySet()) {
if (currentTime > (timeMap.get(key) + expiryInMillis)) {
V value = remove(key);
timeMap.remove(key);
System.out.println("Removing : " + sdf.format(new Date()) + " : " + key + " : " + value);
}
}
}
}
}
Git Repo Link (리스너 구현)
https://github.com/vivekjustthink/WeakConcurrentHashMap
건배!!
자체 만료 해시 맵의 구현 을 시도해 볼 수 있습니다 . 이 구현에서는 스레드를 사용하여 만료 된 항목을 제거하지 않고 모든 작업에서 자동으로 정리되는 DelayQueue 를 사용 합니다 .
: 아파치 커먼즈지도 항목을 만료하기위한 장식이 PassiveExpiringMap 구아바에서 캐시보다는 그것의 더 간단합니다.
추신. 동기화되지 않았습니다.
Google 컬렉션 (구아바)에는 시간 제한 (만료)을 설정할 수 있는 MapMaker 가 있으며 팩토리 방법을 사용하여 선택한 인스턴스를 생성 할 때 약하거나 약한 참조를 사용할 수 있습니다.
ehcache와 같은 소리는 원하는 것을 과도하게 사용하지만 외부 구성 파일이 필요하지 않습니다.
일반적으로 구성을 선언적 구성 파일로 이동하는 것이 좋습니다 (따라서 새 설치에 다른 만료 시간이 필요할 때 다시 컴파일 할 필요는 없음). 그러나 전혀 필요하지는 않지만 프로그래밍 방식으로 구성 할 수 있습니다. http://www.ehcache.org/documentation/user-guide/configuration
Apache MINA 프로젝트의 Expiring Map http://www.java2s.com/Code/Java/Collections-Data-Structure/ExpiringMap.htm 클래스를 사용해보십시오.
간단한 것이 필요한 사람은 다음과 같습니다. 간단한 키 만료 집합입니다. 지도로 쉽게 변환 될 수 있습니다.
public class CacheSet<K> {
public static final int TIME_OUT = 86400 * 1000;
LinkedHashMap<K, Hit> linkedHashMap = new LinkedHashMap<K, Hit>() {
@Override
protected boolean removeEldestEntry(Map.Entry<K, Hit> eldest) {
final long time = System.currentTimeMillis();
if( time - eldest.getValue().time > TIME_OUT) {
Iterator<Hit> i = values().iterator();
i.next();
do {
i.remove();
} while( i.hasNext() && time - i.next().time > TIME_OUT );
}
return false;
}
};
public boolean putIfNotExists(K key) {
Hit value = linkedHashMap.get(key);
if( value != null ) {
return false;
}
linkedHashMap.put(key, new Hit());
return true;
}
private static class Hit {
final long time;
Hit() {
this.time = System.currentTimeMillis();
}
}
}
구아바 캐시는 구현이 쉬우 며 구아바 캐시를 사용하여 시간 기반 키를 만료시킬 수 있습니다. 나는 전체 게시물을 읽었으며 아래는 내 연구의 핵심을 제공합니다.
cache = CacheBuilder.newBuilder().refreshAfterWrite(2,TimeUnit.SECONDS).
build(new CacheLoader<String, String>(){
@Override
public String load(String arg0) throws Exception {
// TODO Auto-generated method stub
return addcache(arg0);
}
}
참조 : 구아바 캐시 예제
일반적으로 캐시는 일정 시간 동안 개체를 유지해야하며 나중에 개체를 노출해야합니다. 무엇 개체를 유지하는 좋은 시간은 사용 사례에 따라 달라집니다. 나는 스레드 나 스케줄러가없는이 일을 간단하게 원했습니다. 이 방법은 저에게 효과적입니다. SoftReference
s 와 달리 객체는 최소한의 시간 동안 사용할 수 있습니다. 그러나 태양이 붉은 거인으로 변할 때까지 기억 속에 남아 있지 마십시오 .
사용 예제에서는 요청이 아주 최근에 수행되었는지 여부를 확인할 수있는 느린 응답 시스템을 생각해보십시오.이 경우에는 바쁜 사용자가 버튼을 여러 번 누르더라도 요청 된 조치를 두 번 수행하지 않아야합니다. 그러나 얼마 후 같은 행동이 요청되면 다시 수행되어야한다.
class Cache<T> {
long avg, count, created, max, min;
Map<T, Long> map = new HashMap<T, Long>();
/**
* @param min minimal time [ns] to hold an object
* @param max maximal time [ns] to hold an object
*/
Cache(long min, long max) {
created = System.nanoTime();
this.min = min;
this.max = max;
avg = (min + max) / 2;
}
boolean add(T e) {
boolean result = map.put(e, Long.valueOf(System.nanoTime())) != null;
onAccess();
return result;
}
boolean contains(Object o) {
boolean result = map.containsKey(o);
onAccess();
return result;
}
private void onAccess() {
count++;
long now = System.nanoTime();
for (Iterator<Entry<T, Long>> it = map.entrySet().iterator(); it.hasNext();) {
long t = it.next().getValue();
if (now > t + min && (now > t + max || now + (now - created) / count > t + avg)) {
it.remove();
}
}
}
}
참고 URL : https://stackoverflow.com/questions/3802370/java-time-based-map-cache-with-expiring-keys
'Programing' 카테고리의 다른 글
기본 키는 MySQL에서 자동으로 색인됩니까? (0) | 2020.04.13 |
---|---|
mv가 존재하지 않을 경우 이동시킬 디렉토리를 작성하는 방법이 있습니까? (0) | 2020.04.13 |
vi에서 한 파일의 내용을 다른 파일로 복사하여 붙여 넣기 (0) | 2020.04.13 |
PHP로 메모리를 비우는 데 더 좋은 점 : unset () 또는 $ var = null (0) | 2020.04.13 |
Java 8의 LocalDateTime에서 밀리 초를 얻는 방법 (0) | 2020.04.13 |