WeakHashMap의 사용 장면
3677 단어 JAVA 베이스.
Car car = new Car(22000,"silver");
WeakReference weakCar = new WeakReference(car);
HashMap과 WeakHashMap의 차이점도 여기에 있다. HashMap의 키는 실제 대상에 대한 강력한 인용이다. 약한 인용 (Weak Reference) 의 특징은 gc 라인에서 약한 인용만 가리키는 것을 발견하면 메모리를 삭제하고 회수합니다.또한 참조 대기열queue에 WeakReference가 추가됩니다. 은 관련 개념을 이해한 후 WeakHashMap의 실제 응용에 대해 궁금했다.그리고tomcat의 원본에서 캐시를 실행할 때 WeakHashMap을 사용합니다.
package org.apache.tomcat.util.collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
public final class ConcurrentCache {
private final int size;
private final Map eden;
private final Map longterm;
public ConcurrentCache(int size) {
this.size = size;
this.eden = new ConcurrentHashMap<>(size);
this.longterm = new WeakHashMap<>(size);
}
public V get(K k) {
V v = this.eden.get(k);
if (v == null) {
synchronized (longterm) {
v = this.longterm.get(k);
}
if (v != null) {
this.eden.put(k, v);
}
}
return v;
}
public void put(K k, V v) {
if (this.eden.size() >= size) {
synchronized (longterm) {
this.longterm.putAll(this.eden);
}
this.eden.clear();
}
this.eden.put(k, v);
}
}
원본 코드에는 eeden과 longterm의 두 개의 맵이 있는데 jvm 더미에 대해 알고 있으면tomcat은 여기에서 ConcurrentHashMap과 WeakHashMap을 사용하여 세대별 캐시를 만들었을 것으로 추정된다.put 방법에서 k-v를 삽입할 때, 먼저 eeden 캐시 용량이 초과되었는지 검사합니다.초과하지 않으면 바로 Eden 캐시에 넣고, 초과하면 longterm을 잠그고 Eden의 모든 k-v를 longterm에 넣습니다.eeden을 비우고 k-v에 삽입합니다.get 방법에서도 eeden에서 대응하는 v를 우선적으로 찾고, 없으면 롱터m 캐시에 들어가서 찾으면 eeden 캐시를 넣고 되돌려줍니다. 이러한 디자인을 통해 상대적으로 자주 사용하는 대상은 모두 eeden 캐시에서 찾을 수 있고 자주 사용하지 않는 대상은longterm 캐시에 들어간다.롱터미널의 키의 실제 대상이 다른 인용이 그를 가리키지 않을 때 gc는 hp에서 이 약한 인용이 가리키는 실제 대상을 자동으로 회수하고 약한 인용은 인용 대기열에 들어간다.longterm에서 expungeStale Entries () 방법을 호출하여 대기열의 약한 인용을 반복적으로 인용하고 대응하는 Entry를 제거하면 메모리 공간의 낭비를 초래하지 않습니다.