codestory

Die Anleitung zu Java WeakReference

  1. WeakReference
  2. Primitive Inner Object
  3. Non-Primitive Inner Object
  4. WeakReference(T, ReferenceQueue<? super T>)
  5. Complex example

1. WeakReference

Die Klasse java.lang.ref.WeakReference wird verwendet, um ein Objekt zu erstellen, das ein anderes Objekt umschließt - innerObject. Das Objekt, das es umschließt, kann vom Garbage Collector (GC) aus dem Speicher entfernt werden, wenn es nicht mehr an einem anderen Ort verwendet wird, der stärker als GC ist.
AnyObject.java
package org.o7planning.beans;

public class AnyObject {
    private String val;
    public AnyObject(String val) {
        this.val = val;
    }
    public String getVal() {
        return this.val;
    }
}
Zum einfachen Verständnis sehen Sie sich den folgenden Code an::
AnyObject innerObject = new AnyObject("Obj1");

WeakReference weakRef = new WeakReference(innerObject);
Trong đoạn code trên chúng ta có đối tượng innerObject, nó được sử dụng như một tham số để tạo ra đối tượng weakRef, hay nói cách innerObject đang được sử dụng bởi weakRef.
Im obigen Code haben wir ein Objekt innerObject, das als Parameter verwendet wird, um ein Objekt weakRef Objekt zu erstellen, oder mit anderen Worten, innerObject wird von weakRef verwendet.
Im gesunden Menschenverstand ist ein Objekt, das irgendwo verwendet wird, nützlich und kann nicht aus dem Speicher entfernt werden. Allerdings ist WeakReference eine spezielle Klasse, die als schwächer als Garbage Collector (GC) gilt. Ein in eine WeakReference eingeschlossenes Objekt kann immer noch von GC aus dem Speicher entfernt werden, wenn es nicht mehr an einem anderen Ort verwendet wird, der stärker als GC ist.
WeakReference_obj_ex1.java
package org.o7planning.weakreference.ex;

import java.lang.ref.WeakReference;

import org.o7planning.beans.AnyObject;

public class WeakReference_obj_ex1 {

    public static void main(String[] args) throws InterruptedException {
        // Create innerObject reference points to AnyObject("Obj1").
        AnyObject innerObject = new AnyObject("Obj1");
        // Create WeakReference object using innerObject reference.
        WeakReference<AnyObject> weakRef = new WeakReference<AnyObject>(innerObject);
        
        System.out.println("weakRef.get(): " + weakRef.get());
        
        // Set innerObject reference to null (Points to null).
        innerObject = null;

        System.out.println("\nCall System.gc().\n");
        System.gc();
        Thread.sleep(3000);
        
        System.out.println("weakRef.get(): " + weakRef.get());
    }
}
Output:
weakRef.get(): org.o7planning.beans.AnyObject@5e91993f

Call System.gc().

weakRef.get(): null
Im obigen Beispiel rufen wir die Methode System.gc() auf, um Garbage Collector anzuweisen, zu funktionieren. Dieser Antrag hat keine sofortige Wirkung. Im Grunde ist GC eine klugee und komplexe Maschine, die automatisch arbeitet und in die Sie nur eingeschränkt eingreifen können.
Im nächsten Beispiel werden wir die Methode System.gc() nicht aktiv aufrufen, aber GC entfernt das in WeakReference eingeschlossene Objekt nach einer Weile immer noch, wenn es nicht mehr an einem anderen Ort verwendet wird, der stärker als GC ist
WeakReference_obj_ex2.java
package org.o7planning.weakreference.ex;

import java.lang.ref.WeakReference;

import org.o7planning.beans.AnyObject;

public class WeakReference_obj_ex2 {

    public static void main(String[] args) throws InterruptedException {
         // Create innerObject reference points to AnyObject("Obj1").
        AnyObject innerObject = new AnyObject("Obj1");
        // Create WeakReference object using innerObject reference.
        WeakReference<AnyObject> weakRef = new WeakReference<AnyObject>(innerObject);
        
        System.out.println("weakRef.get(): " + weakRef.get());

        int i = 0;
        while(true)  {
            AnyObject innerObj = weakRef.get();
            if(innerObj == null)  {
                System.out.println("Inner object is removed by Garbage Collector");
                System.out.println("weakRef.get(): " + innerObj);
                break;
            }
            i++;
            System.out.println(i+ " weakRef.get(): " + innerObj);
        }
    }
}
Output:
weakRef.get(): org.o7planning.beans.AnyObject@5e91993f
1 weakRef.get(): org.o7planning.beans.AnyObject@5e91993f
2 weakRef.get(): org.o7planning.beans.AnyObject@5e91993f

.....

283516 weakRef.get(): org.o7planning.beans.AnyObject@5e91993f
283517 weakRef.get(): org.o7planning.beans.AnyObject@5e91993f
283518 weakRef.get(): org.o7planning.beans.AnyObject@5e91993f
Inner object is removed by Garbage Collector
weakRef.get(): null
WeakReference constructors
WeakReference(T referent)

WeakReference(T referent, ReferenceQueue<? super T> q)
Alle Methoden von WeakReference werden von der Elternklasse geerbt
// Methods inherited from parent.
public T get()  
public void clear()  
public boolean isEnqueued()  
public boolean enqueue()

2. Primitive Inner Object

Ein primitiver Wert ist keine Referenz, obwohl er wie eine Referenz geschrieben werden kann. Wenn es also in eine WeakReference eingeschlossen ist, wird es von GC nicht aus dem Speicher entfernt.
Integer innerObj1 = 1000;
Double innerObj2 = 2000.2;
String innerObj3 = "SomeString";
Zum Beispiel:
WeakReference_primitive_ex1.java
package org.o7planning.weakreference.ex;

import java.lang.ref.WeakReference;

public class WeakReference_primitive_ex1 {

    public static void main(String[] args) throws InterruptedException {
        Integer innerObj1 = 100;
        String  innerObj2 = "SomeString";
        
        WeakReference<Integer> weakRef1 = new WeakReference<Integer>(innerObj1);
        WeakReference<String> weakRef2 = new WeakReference<String>(innerObj2);
        
        System.out.println("weakRef1.get(): "  + weakRef1.get());
        System.out.println("weakRef2.get(): "  + weakRef2.get());
        
        // Points to null.
        innerObj1 = null;
        innerObj2 = null;
        
        System.out.println("\n--- Call System.gc(): ---\n");
        // Call GC:
         System.gc();
        Thread.sleep(3000);
        
        
        System.out.println("weakRef1.get(): "  + weakRef1.get());
        System.out.println("weakRef2.get(): "  + weakRef2.get());
    }
}
Output:
weakRef1.get(): 100
weakRef2.get(): SomeString

--- Call System.gc(): ---

weakRef1.get(): 100
weakRef2.get(): SomeString

3. Non-Primitive Inner Object

Wenn ein Objekt vom Operator "new" erstellt und in eine WeakReference eingeschlossen wird, wird es von GC aus dem Speicher entfernt, wenn es nicht mehr an einem anderen Ort verwendet wird, der stärker als GC ist.
AnyObject innerObj1 = new AnyObject("Obj1");
String innerObj2 = new String("Obj2");
Integer innerObj3 = new Integer(1000);
String innerObj4 = new String("Obj4");

WeakReference<AnyObject> weakRef = new WeakReference<AnyObject>(innerObj1);
Das in eine WeakReference eingebettete Objekt fungiert als Diner in einem Restaurant. Wenn die Gäste mit dem Essen fertig sind, sind sie bereit, den Tisch zu verlassen, auch wenn das Restaurant zu dieser Zeit viele leere Tische hat. SoftReference unterscheidet sich ein wenig von WeakReference, Gäste können sich zurücklehnen und nur gehen, wenn das Restaurant keine freien Tische mehr hat oder die Anzahl der verfügbaren freien Tische unter einem sicheren Wert liegt

4. WeakReference(T, ReferenceQueue<? super T>)

Erstellen Sie ein Objekt WeakReference, das das Objekt innerObject umschließt. Wenn innerObject von GC aus dem Speicher entfernt wird, wird dieses Objekt WeakReference der queue hinzugefügt.
WeakReference(T innerObject, ReferenceQueue<? super T> queue)
Zum Beispiel:
WeakReference_c2_ex1.java
package org.o7planning.weakreference.ex;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;

import org.o7planning.beans.AnyObject;

public class WeakReference_c2_ex1 {

    public static void main(String[] args) throws InterruptedException {

        AnyObject myAnyObject1 = new AnyObject("Obj1");
        AnyObject myAnyObject2 = new AnyObject("Obj2");

        ReferenceQueue<AnyObject> queue = new ReferenceQueue<AnyObject>();
        //
        WeakReference<AnyObject> weakRef1 = new WeakReference<AnyObject>(myAnyObject1, queue);
        WeakReference<AnyObject> weakRef2 = new WeakReference<AnyObject>(myAnyObject2, queue);

        System.out.println("weakRef1: " + weakRef1);
        System.out.println("weakRef2: " + weakRef2);
        System.out.println("weakRef1.get(): " + weakRef1.get());
        System.out.println("weakRef2.get(): " + weakRef2.get());

        // Set myAnyObject1 reference to null (Points to null).
        myAnyObject1 = null;

        System.out.println("\nCall System.gc().\n");
        System.gc();
        Thread.sleep(3000);

        // myAnyObject2 is still used.
        System.out.println("myAnyObject2: " + myAnyObject2);

        System.out.println("weakRef1.get(): " + weakRef1.get());
        System.out.println("weakRef2.get(): " + weakRef2.get());

        Reference<? extends AnyObject> removed = null;
        while ((removed = queue.poll()) != null) {
            System.out.println("removed: " + removed);
        }
    }
}
Output:
weakRef1: java.lang.ref.WeakReference@5e91993f
weakRef2: java.lang.ref.WeakReference@156643d4
weakRef1.get(): org.o7planning.beans.AnyObject@123a439b
weakRef2.get(): org.o7planning.beans.AnyObject@7de26db8

Call System.gc().

myAnyObject2: org.o7planning.beans.AnyObject@7de26db8
weakRef1.get(): null
weakRef2.get(): org.o7planning.beans.AnyObject@7de26db8
removed: java.lang.ref.WeakReference@5e91993f

5. Complex example

Als nächstes brauchen wir ein komplexeres Beispiel. In diesem Beispiel werden Objekte Employee zu einer Firma hinzugefügt. Und ein Objekt Liste, das eine Liste schwacher Verweise auf jedes Objekt Employee enthält. Solange das Company die Objekte Employee speichert, werden sie von GC nicht aus dem Speicher entfernt.
WeakReference_ex1.java
package org.o7planning.weakreference.ex;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class WeakReference_ex1 {

    public static void main(String[] args) throws InterruptedException {
        Employee tom = new Employee("Tom");
        Employee jerry = new Employee("Jerry");
        Employee donald = new Employee("Donald");

        Employee[] employees = new Employee[] { tom, jerry, donald };

        Company company = new Company();

        ReferenceQueue<Employee> queue = new ReferenceQueue<>();
        List<WeakReference<Employee>> empListWeak = new ArrayList<WeakReference<Employee>>();

        for (int i = 0; i < employees.length; i++) {
            company.addEmployee(employees[i]);

            empListWeak.add(new WeakReference<Employee>(employees[i], queue));
        }
        // Free up the array.
        employees = null;

        System.out.println("Queue's polling returns null? " + (queue.poll() == null));

        for (WeakReference<Employee> wref : empListWeak) {
            System.out.println("wref.get().getFullName(): " + wref.get().getFullName());
        }

        //
        System.out.println("\n--- Remove some employees from company: ---\n");
        company.removeEmployee(tom);
        company.removeEmployee(jerry);
        tom = null;
        jerry = null;
        donald = null; // 'donald' is still used in company.

        System.gc();
        Thread.sleep(3000);

        Reference<? extends Employee> wref = null;
        System.out.println("Poll weak emp references garbage collected");
        while ((wref = queue.poll()) != null) {
            System.out.println("WeakReference of Emp removed from queue: " + wref);

        }
        System.out.println("done");
    }
}

class Employee {
   private String fullName;
   public Employee(String fullName)  {
       this.fullName = fullName;
   }
   public String getFullName()  {
       return this.fullName;
   }
}


class Company {
    private Set<Employee> employees = new HashSet<Employee>();

    public void addEmployee(Employee employee) {
        this.employees.add(employee);
    }

    public void removeEmployee(Employee employee) {
        employees.remove(employee);
    }
}
Output:
Queue's polling returns null? true
wref.get().getFullName(): Tom
wref.get().getFullName(): Jerry
wref.get().getFullName(): Donald

--- Remove some employees from company: ---

Poll weak emp references garbage collected
WeakReference of Emp removed from queue: java.lang.ref.WeakReference@1175e2db
WeakReference of Emp removed from queue: java.lang.ref.WeakReference@36aa7bc2
done

Java Grundlagen

Show More