Korzystanie z języka Java

Czy SoftReference i WeakReference naprawdę pomagają tylko wtedy, gdy są tworzone jako zmienne instancji? Czy jest jakaś korzyść z używania ich w zakresie metod?

Druga duża część to ReferenceQueue. Oprócz możliwości śledzenia, które odwołania są określone śmieciami, czy Reference.enqueue() mogą być użyte do przymusowej rejestracji obiektu do zbierania śmieci?

Na przykład, czy warto stworzyć metodę, która pobiera duże zasoby pamięci (utrzymywane przez silne referencje) w obiekcie i tworzy odniesienia do zapytasz ich?

Object bigObject;
public void dispose() {
    ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
    WeakReference<Object> ref = new WeakReference<Object>(bigObject, queue);
    bigObject = null;
    ref.enqueue();
}

(wyobraź sobie, że obiekt w tym przypadku reprezentuje typ obiektu, który wykorzystuje dużo pamięci... jak BufferedImage czy coś)

Czy to ma jakiś realistyczny efekt? Czy to tylko strata kodu?
Author: Nathan, 2013-01-22

4 answers

Jednym z popularnych idiomów z kolejkami referencyjnymi jest np. podklasa WeakReference, aby dołączyć informacje potrzebne do posprzątania rzeczy, a następnie do ankiety ReferenceQueue, aby uzyskać zadania czyszczenia.

ReferenceQueue<Foo> fooQueue = new ReferenceQueue<Foo>();

class ReferenceWithCleanup extends WeakReference<Foo> {
  Bar bar;
  ReferenceWithCleanup(Foo foo, Bar bar) {
    super(foo, fooQueue);
    this.bar = bar;
  }
  public void cleanUp() {
    bar.cleanUp();
  }
}

public Thread cleanupThread = new Thread() {
  public void run() {
    while(true) {
      ReferenceWithCleanup ref = (ReferenceWithCleanup)fooQueue.remove();
      ref.cleanUp();
    }
  }
}

public void doStuff() {
  cleanupThread.start();
  Foo foo = new Foo();
  Bar bar = new Bar();
  ReferenceWithCleanup ref = new ReferenceWithCleanup(foo, bar);
  ... // From now on, once you release all non-weak references to foo,
      // then at some indeterminate point in the future, bar.cleanUp() will
      // be run. You can force it by calling ref.enqueue().
}

Na przykład implementacja CacheBuilder Po wybraniu weakKeys wykorzystuje to podejście.

 34
Author: Louis Wasserman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-17 15:06:53

Jeśli obiekt ma tylko WeakReference s(lub żadnych odniesień!), może być zbierana za każdym razem, gdy Java potrzebuje więcej miejsca w pamięci. Tak więc, używasz WeakReference s, gdy chcesz, aby obiekt pozostał w pamięci, ale nie potrzebujesz go tak źle (np. jeśli Java potrzebuje śmieci, nie ma problemu, możesz go jakoś odzyskać i w międzyczasie Java ma lepszą wydajność)

Zapytanie a WeakReference pozwala na iterację ReferenceQueue i określenie, które referencje mają zostały zebrane śmieci, a które nie. To wszystko - więc rób to tylko wtedy, gdy musisz to wiedzieć.

Czytaj więcej: http://weblogs.java.net/blog/2006/05/04/understanding-weak-references

 6
Author: Patashu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-04 17:10:23

Jedną z najczęstszych rzeczy do zrobienia jest tworzenie map miękkich odniesień.

Map<String, SoftReference<BigThing>> cache = new HashMap<>();
Set<String> thingsIAmCurrentlyGetting = new HashSet<String>();
Object mutex = new Object();

BigThing getThing(String key) {
  synchronized(mutex) {
    while(thingsIAmCurrentlyGetting.contains(key)) {
      mutex.wait();
    }
    SoftReference<BigThing> ref = cache.get(key);
    BigThing bigThing = ref == null ? null : ref.get();
    if(bigThing != null) return bigThing;
    thingsIAmCurrentlyGetting.add(key);
  }

  BigThing bigThing = getBigThing(key); // this may take a while to run.

  synchronized(mutex) {
    cache.put(key, bigThing);
    thingsIAmCurrentlyGetting.remove(key);
    mutex.notifyAll();
  }

  return bigThing;
}

Pokazuję tutaj moją starą szkołę - nowe pakiety Javy prawdopodobnie mają znacznie lepsze sposoby na to.

 5
Author: PaulMurrayCbr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-22 17:10:28

Nie wiem, o co tu chodzi, ale:

1) soft ref staraj się zachować referencję, dopóki jvm naprawdę naprawdę potrzebuje pamięci. Świetne do pamięci podręcznej, esp LRU. Spójrz na wiele przykładów w Guava.

2) słaby ref nie próbuj w ogóle uniemożliwiać GC uwolnienia obiektu. Są one używane, jeśli chcesz wiedzieć, czy ten obiekt jest nadal używany gdzieś. Na przykład są one używane do przechowywania informacji o wątkach i klasach, tak że gdy wątek lub klasa nie jest już używana, możemy odrzucić metainfo związane z tym.

3) phantom ref są jak słabe, ale bez odniesienia do rzeczywistego obiektu. W ten sposób możesz być pewien, że przejście fantomu nie może wznowić rzeczywistego obiektu (jest to ryzyko ze słabym ref). Również phantom ref blokują obiekt, który należy zebrać, dopóki nie wyczyścisz ref.

ReferenceQueue: nie enque rzeczy tam. gc ci pomoże. Pozwalają one wiedzieć, kiedy niektóre referencje zostaną wydane, bez konieczności sprawdzania ich jeden przez jeden.

 1
Author: Uberto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-25 10:23:38