약한 해쉬 맵이나 약점을 언제 사용 하시겠습니까?
-
03-07-2019 - |
문제
약한 참조의 사용은 내가 구현을 본 적이없는 것입니다. 언제 a WeakHashMap
또는 WeakReference
그리고 어떻게 사용 되었습니까?
해결책
강력한 참조의 한 가지 문제는 캐싱, 특히 이미지와 같은 매우 큰 구조를 가진 캐싱입니다. 내가 작업하는 웹 사이트 디자인 도구와 같이 사용자가 제공 한 이미지와 함께 작업 해야하는 응용 프로그램이 있다고 가정 해 봅시다. 당연히 디스크에서로드하는 것은 매우 비싸고 메모리에 메모리에 두 개의 (잠재적으로 거대한) 이미지의 사본을 한 번에 가질 가능성을 피하려고하기 때문에 이러한 이미지를 캐시하려고합니다.
이미지 캐시는 절대적으로 필요하지 않을 때 이미지를 다시로드하는 것을 방지하기 때문에 캐시에 이미 메모리에있는 이미지에 대한 참조가 포함되어 있어야한다는 것을 빨리 알게 될 것입니다. 그러나 평범한 강력한 참조를 통해 그 참조 자체는 이미지가 메모리에 남아 있어야하므로 이미지가 더 이상 메모리에 필요하지 않은시기를 결정하고 캐시에서 제거하여 쓰레기 수집을받을 수있게됩니다. 쓰레기 수집기의 동작을 복제하고 물체가 메모리에 있어야하는지 여부를 수동으로 결정해야합니다.
약한 참조 이해, 에단 니콜라스
다른 팁
명확한 한 가지 구별은 WeakReference
그리고 a SoftReference
.
기본적으로 a WeakReference
JVM에 의해 GC-D가 될 것입니다. 딱딱한 그것에 대한 참조. ㅏ SoftReference
반면에 D 물체는 실제로 메모리를 되 찾아야 할 때까지 쓰레기 수집기가 남겨 두는 경향이 있습니다.
캐시 위치 가치 내부에 붙어 있습니다 WeakReference
S는 꽤 쓸모가 없을 것입니다 (a WeakHashMap
, 그것은 약하게 참조되는 키입니다). SoftReferences
캐시를 구현할 때 값을 감싸고 사용 가능한 메모리로 줄어들 수있는 캐시를 구현할 때 값을 감싸는 데 유용합니다.
하나의 일반적인 사용 WeakReference
모래 WeakHashMap
특히 S는 객체에 속성을 추가하는 것입니다. 때때로 객체에 일부 기능이나 데이터를 추가하려고하지만 서브 클래싱 및/또는 구성이 옵션이 아닙니다.이 경우 명백한 일은 추가하려는 속성에 확장하려는 객체를 연결하는 해시 맵을 만드는 것입니다. . 그런 다음 속성이 필요할 때마다지도에서 찾을 수 있습니다. 그러나 부동산을 추가하는 객체가 파괴되고 많이 생성되는 경향이있는 경우, 많은 메모리를 차지하는지도에서 많은 오래된 개체로 끝날 수 있습니다.
사용하는 경우 a WeakHashMap
대신 객체는 더 이상 프로그램의 나머지 부분에서 더 이상 사용되지 않아도 맵을 남겨 둡니다. 이는 원하는 동작입니다.
데이터를 추가하기 위해이 작업을 수행해야했습니다. java.awt.Component
1.4.2에서 1.5 사이의 JRE의 변화를 해결하기 위해 int (관심있는 모든 구성 요소를 서브 클래싱하여 고칠 수있었습니다.JButton
, JFrame
, JPanel
....) 그러나 이것은 훨씬 적은 코드로 훨씬 쉬웠습니다.
또 다른 유용한 사례 WeakHashMap
그리고 WeakReference
a 리스너 레지스트리 구현.
특정 이벤트를 듣고 싶은 것을 만들 때 일반적으로 청취자를 등록합니다.
manager.registerListener(myListenerImpl);
만약 manager
청취자를 a WeakReference
, 그것은 당신이 레지스터를 제거 할 필요가 없다는 것을 의미합니다. manager.removeListener(myListenerImpl)
청취자 또는 청취자를 고정하는 구성 요소를 사용할 수 없게되면 자동으로 제거되기 때문입니다.
물론 여전히 청취자를 수동으로 제거 할 수 있습니다. 하지만 그렇지 않거나 잊지 않으면 메모리 누출이 발생하지 않으며 청취자가 쓰레기를 수집하는 것을 막지 않습니다.
어디에 WeakHashMap
사진에 들어 오시겠습니까?
등록 된 청취자를 WeakReference
이 참조를 저장하려면 컬렉션이 필요합니다. 아니요 WeakHashSet
표준 Java 라이브러리의 구현 a WeakHashMap
그러나 우리는 후자를 쉽게 사용하여 첫 번째 기능의 기능을 "구현"할 수 있습니다.
Set<ListenerType> listenerSet =
Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());
이것으로 listenerSet
새 리스너를 등록하려면 세트에 추가해야하며 명시 적으로 제거되지 않더라도 청취자가 더 이상 참조되지 않으면 JVM에 의해 자동으로 제거됩니다.
이 블로그 게시물은 두 클래스의 사용을 보여줍니다. Java : ID의 동기화. 사용법은 다음과 같이됩니다.
private static IdMutexProvider MUTEX_PROVIDER = new IdMutexProvider();
public void performTask(String resourceId) {
IdMutexProvider.Mutex mutext = MUTEX_PROVIDER.getMutex(resourceId);
synchronized (mutext) {
// look up the resource and do something with it
}
}
idmutextProvider는 동기화 할 ID 기반 객체를 제공합니다. 요구 사항은 다음과 같습니다.
- 동등한 ID를 동시에 사용하기 위해 동일한 개체에 대한 참조를 반환해야합니다.
- 다른 ID에 대해 다른 객체를 반환해야합니다
- 릴리스 메커니즘이 없음 (객체는 공급자에게 반환되지 않음)
- 누출되지 않아야합니다 (사용하지 않은 물체는 쓰레기 수집 자격이 있습니다)
이것은 유형의 내부 스토리지 맵을 사용하여 달성됩니다.
WeakHashMap<Mutex, WeakReference<Mutex>>
객체는 핵심과 가치입니다. 맵 외부에 아무것도 물체에 대한 단단한 참조가 없으면 쓰레기를 수집 할 수 있습니다. 지도의 값은 하드 참조로 저장되므로 값은 약한 참조 메모리 누출을 방지합니다. 이 마지막 지점은 Javadoc.
예를 들어 특정 클래스의 생성 된 모든 개체를 추적하려는 경우. 이러한 물체를 수집하는 것을 여전히 수집하기 위해서는 물체 자체 대신 객체에 대한 약한 참조 목록/지도를 유지합니다.
이제 누군가가 나에게 팬텀 참조를 설명 할 수 있다면 행복 할 것입니다 ...
위에서 언급 한 바와 같이, 강한 참조가 존재하는 한 약한 기준이 유지된다.
예를 들어, 대상 객체에 대한 기본 참조가 사라지면 청취자 내부의 약점을 사용하여 청취자가 더 이상 활성화되지 않도록하는 것입니다. 이는 약점이 리스너 목록에서 제거되었음을 의미하지는 않지만 정리가 여전히 필요하지만 예를 들어 예정된 시간에 수행 할 수 있습니다. 이것은 또한 물체가 강한 참고 문헌을 들지 못하게하는 것을 방지하는 효과가 있으며 결국 메모리의 원천이됩니다. 예 : 스윙 GUI 구성 요소는 창보다 수명주기가 길어진 모델을 참조합니다.
위에서 설명한대로 청취자와 함께 연주하는 동안 우리는 객체가 사용자의 관점에서 "즉시"수집된다는 것을 빠르게 깨달았습니다.
약점을 위해 내가 가진 실제 세계 사용 중 하나는 거의 사용되지 않는 단일, 매우 큰 물체가있는 경우입니다. 필요하지 않은 경우 메모리에 유지하고 싶지 않습니다. 그러나 다른 스레드에 동일한 객체가 필요한 경우 메모리에 두 개를 원하지 않습니다. 물체에 대한 약한 참조와 그것을 사용하는 방법에 대한 단단한 참조를 유지할 수 있습니다. 메소드가 모두 완료되면 물체가 수집됩니다.
"New Beakhashmap ()"에 대한 Google 코드 검색을 수행했습니다.
나는 GNU ClassPath 프로젝트에서 많은 경기를 받았고
- Apache Xbean 프로젝트 : 약한 해시 모드. 자바
- 아파치 루센 프로젝트 : CachingWrapperFilter.java
약점 해쉬 맵을 사용하여 넓은 객체 생성을 위해 리소스가없는 캐싱을 구현할 수 있습니다.
그러나 변한 물체를 갖는 것은 바람직하지 않습니다. 텍스트 검색 엔진에 대한 쿼리 결과 (실행하는 데 약 400ms)를 캐시하는 데 사용했는데 거의 업데이트되지 않았습니다.