Użycie słabych referencji jest czymś, czego nigdy nie widziałem implementacji, więc próbuję dowiedzieć się, jaki jest ich przypadek użycia i jak ta implementacja będzie działać. Kiedy musiałeś użyć WeakHashMap
lub WeakReference
i jak był używany?
Użycie słabych referencji jest czymś, czego nigdy nie widziałem implementacji, więc próbuję dowiedzieć się, jaki jest ich przypadek użycia i jak ta implementacja będzie działać. Kiedy musiałeś użyć WeakHashMap
lub WeakReference
i jak był używany?
Odpowiedzi:
Jednym z problemów z silnymi odwołaniami jest buforowanie, szczególnie w przypadku bardzo dużych struktur, takich jak obrazy. Załóżmy, że masz aplikację, która musi pracować z obrazami dostarczonymi przez użytkowników, na przykład narzędzie do projektowania witryn internetowych, nad którym pracuję. Oczywiście chcesz buforować te obrazy, ponieważ ładowanie ich z dysku jest bardzo kosztowne i chcesz uniknąć możliwości posiadania dwóch kopii (potencjalnie gigantycznego) obrazu w pamięci jednocześnie.
Ponieważ pamięć podręczna obrazów ma uniemożliwić nam ponowne ładowanie obrazów, gdy nie jest to absolutnie konieczne, szybko zorientujesz się, że pamięć podręczna zawsze powinna zawierać odniesienie do dowolnego obrazu, który jest już w pamięci. Jednak w przypadku zwykłych silnych odniesień, to samo odniesienie wymusi pozostanie obrazu w pamięci, co wymaga od ciebie jakoś określenia, kiedy obraz nie jest już potrzebny w pamięci i usunięcia go z pamięci podręcznej, aby kwalifikował się do czyszczenia pamięci. Jesteś zmuszony do skopiowania zachowania modułu odśmiecania pamięci i ręcznego określenia, czy obiekt powinien znajdować się w pamięci.
Zrozumienie słabych odniesień , Ethan Nicholas
WeakHashMap
.
WeakReference
przeciw SoftReference
Jedno rozróżnienie, które należy wyjaśnić, to różnica między a WeakReference
i a SoftReference
.
Zasadniczo WeakReference
będzie to GC-d przez JVM chętnie, gdy obiekt, do którego istnieje odwołanie, nie ma do niego żadnych twardych odniesień. Z SoftReference
drugiej strony obiekt d będzie miał tendencję do pozostawiania go przez moduł odśmiecania, dopóki naprawdę nie będzie musiał odzyskać pamięci.
Pamięć podręczna, w której wartości są przechowywane wewnątrz WeakReference
s, byłaby całkiem bezużyteczna (w a WeakHashMap
, to klucze są słabo przywoływane). SoftReferences
są przydatne do zawijania wartości, gdy chcesz zaimplementować pamięć podręczną, która może rosnąć i zmniejszać się wraz z dostępną pamięcią.
W szczególności jednym z powszechnych zastosowań WeakReference
s i WeakHashMap
s jest dodawanie właściwości do obiektów. Czasami chcesz dodać jakąś funkcjonalność lub dane do obiektu, ale podklasy i / lub kompozycja nie są opcją w tym przypadku oczywistą rzeczą byłoby utworzenie hashmapy łączącej obiekt, który chcesz rozszerzyć, do właściwości, którą chcesz dodać . wtedy, gdy potrzebujesz nieruchomości, możesz ją po prostu sprawdzić na mapie. Jeśli jednak obiekty, do których dodajesz właściwości, są często niszczone i często tworzone, możesz skończyć z wieloma starymi obiektami na mapie, które zajmują dużo pamięci.
Jeśli WeakHashMap
zamiast tego użyjesz a, obiekty opuszczą twoją mapę, gdy tylko nie będą już używane przez resztę twojego programu, co jest zachowaniem pożądanym.
Musiałem to zrobić, aby dodać jakieś dane java.awt.Component
, aby ominąć zmianę pomiędzy JRE 1.4.2 i 1.5, mógłbym naprawić go przez instacji każdy składnik byłem zainteresowany int ( JButton
, JFrame
, JPanel
....), ale było to o wiele łatwiej z dużo mniejszą ilością kodu.
Innym przydatnym przypadkiem dla implementacji rejestru nasłuchiwaniaWeakHashMap
i WeakReference
jest .
Kiedy tworzysz coś, co chce posłuchać określonych wydarzeń, zazwyczaj rejestrujesz słuchacza, np
manager.registerListener(myListenerImpl);
Jeśli manager
przechowuje twój słuchacz z a WeakReference
, oznacza to, że nie musisz usuwać rejestru, np. Z a, manager.removeListener(myListenerImpl)
ponieważ zostanie on automatycznie usunięty, gdy twój słuchacz lub twój komponent, który go trzyma, stanie się niedostępny.
Oczywiście nadal możesz ręcznie usunąć nasłuchiwanie, ale jeśli tego nie zrobisz lub zapomnisz, nie spowoduje to wycieku pamięci i nie zapobiegnie gromadzeniu elementów bezużytecznych.
Gdzie pojawia WeakHashMap
się ten obraz?
Rejestr odbiornika, który chce przechowywać zarejestrowane odbiorniki jako WeakReference
s, potrzebuje kolekcji do przechowywania tych odniesień. W WeakHashSet
standardowej bibliotece Javy nie ma implementacji, WeakHashMap
ale możemy z łatwością wykorzystać tę drugą do „zaimplementowania” funkcjonalności pierwszej:
Set<ListenerType> listenerSet =
Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());
Mając to listenerSet
na zarejestrowanie nowego słuchacza wystarczy dodać go do zestawu, a nawet jeśli to nie jest usuwany wyraźnie, gdy słuchacz nie jest wymieniony, zostanie on automatycznie usunięty przez JVM.
WeakHashMap
dotyczy sytuacji, gdy potrzebujesz HashMap
obiektów. Więc wow, nie musisz ręcznie wykonywać hashmap.remove , ponieważ elementy są automatycznie usuwane, gdy obiekt znajdzie się poza zasięgiem! Dosłownie magia! Taka brzydka magiczna sztuczka to kompletny facepalm .
WeakReference
plików znacznie upraszcza podstawę kodu i pozwala uniknąć niepotrzebnych błędów związanych z niepowodzeniem anulowania subskrypcji. Jaki minus?
Ten wpis na blogu demonstruje użycie obu klas: Java: synchronizacja na podstawie identyfikatora . Użycie wygląda mniej więcej tak:
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 zapewnia obiekty oparte na identyfikatorach do synchronizacji. Wymagania są następujące:
Osiąga się to za pomocą wewnętrznej mapy pamięci typu:
WeakHashMap<Mutex, WeakReference<Mutex>>
Obiekt jest jednocześnie kluczem i wartością. Gdy nic poza mapą nie ma twardego odniesienia do obiektu, może zostać wyrzucone do pamięci. Wartości w mapie są przechowywane z twardymi odwołaniami, więc wartość musi być opakowana w WeakReference, aby zapobiec wyciekowi pamięci. Ten ostatni punkt omówiono w pliku javadoc .
Jeśli na przykład chcesz śledzić wszystkie obiekty utworzone w określonej klasie. Aby nadal zezwalać na zbieranie elementów bezużytecznych, zachowujesz listę / mapę słabych odniesień do obiektów zamiast samych obiektów.
Gdyby ktoś mógł mi wyjaśnić odniesienia do widm, byłbym szczęśliwy ...
Jak stwierdzono powyżej, słabe odniesienie utrzymuje się tak długo, jak istnieje silne odniesienie.
Przykładowym zastosowaniem może być użycie WeakReference wewnątrz detektorów, tak aby nasłuchiwacze nie byli już aktywni po zniknięciu głównego odniesienia do ich obiektu docelowego. Należy zauważyć, że nie oznacza to, że WeakReference jest usuwane z listy słuchaczy, czyszczenie jest nadal wymagane, ale można je wykonać na przykład w zaplanowanych godzinach. Ma to również wpływ na to, że słuchany obiekt nie posiada silnych odniesień i ostatecznie staje się źródłem nadmiaru pamięci. Przykład: komponenty Swing GUI odwołujące się do modelu mającego dłuższy cykl życia niż okno.
Podczas zabawy ze słuchaczami, jak opisano powyżej, szybko zdaliśmy sobie sprawę, że obiekty są zbierane „natychmiast” z punktu widzenia użytkownika.
Jednym z rzeczywistych zastosowań, jakie miałem dla WeakReferences, jest pojedynczy, bardzo duży obiekt, który jest rzadko używany. Nie chcesz mieć tego w pamięci, gdy nie jest potrzebny; ale jeśli inny wątek potrzebuje tego samego obiektu, nie chcesz też dwóch z nich w pamięci. Możesz przechowywać gdzieś słabe odniesienie do obiektu, a twarde odniesienia w metodach, które go używają; gdy obie metody zakończą się, obiekt zostanie zebrany.
Wyszukałem w google hasło „nowa WeakHashMap ()”.
Mam kilka dopasowań z projektu GNU classpath i
możesz użyć slabyhashmap, aby zaimplementować buforowanie bez zasobów do ekspansywnego tworzenia obiektów.
ale zauważ, że nie jest pożądane posiadanie zmiennych obiektów. Użyłem go do buforowania wyników zapytań (których wykonanie zajmuje około 400 ms) do wyszukiwarki tekstowej, która rzadko jest aktualizowana.