Руководство Java WeakReference
1. WeakReference
Класс java.lang.ref.WeakReference используется для создания объекта, который обертывает (wrap) другой объект - innerObject. Объект, который он обертывает, может быть удален из памяти by Garbage Collector (GC) (сборщиком мусора), если он больше не используется в другом месте, более сильном, чем GC.
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;
}
}
Для удобства понимания см. code ниже:
AnyObject innerObject = new AnyObject("Obj1");
WeakReference weakRef = new WeakReference(innerObject);
В приведенном выше коде у нас есть объект innerObject, который используется в качестве параметра для создания объекта weakRef, или, другими словами, innerObject используется by weakRef.
В общем смысле, если объект где-то используется, он полезен и не может быть удален из памяти. Однако WeakReference - это особый класс, который считается более слабым, чем Garbage Collector (GC) (сборщик мусора). Объект, завернутый в WeakReference, все еще может быть удален из памяти GC, если он больше не используется в другом месте, более сильном, чем GC.
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
В приведенном выше примере мы вызываем метод System.gc(), чтобы сообщить Garbage Collector о работе. Эта просьба не имеет немедленного действия. По сути, GC - это сложная машина, которая работает автоматически, и вы можете вмешиваться в нее только ограниченным образом.
В следующем примере мы не будем активно вызывать метод System.gc(), но GC все равно удалит объект, завернутый в WeakReference, через некоторое время, если он больше не используется в другом месте, более сильном, чем GC.
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)
Все методы WeakReference наследуются от родительского класса.
// Methods inherited from parent.
public T get()
public void clear()
public boolean isEnqueued()
public boolean enqueue()
2. Primitive Inner Object
Примитивное значение не является ссылкой, хотя его можно записать как ссылку, поэтому, если оно завернуто в WeakReference, оно не будет удалено из памяти by GC.
Integer innerObj1 = 1000;
Double innerObj2 = 2000.2;
String innerObj3 = "SomeString";
Например:
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
Если объект создан оператором "new" и завернут в WeakReference, он будет удален из памяти by GC, если он больше не используется в другом месте, более сильном, чем GC.
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);
Объект, завернутый в WeakReference, действует как посетители в ресторане. Когда посетители заканчивают есть, они готовы покинуть стол, даже если в это время в ресторане много пустых столов. SoftReference немного отличается от WeakReference, посетители могут оставаться и уходить только в том случае, если в ресторане больше нет свободных столов или количество свободных столов меньше безопасного значения.
4. WeakReference(T, ReferenceQueue<? super T>)
Создайте объект WeakReference, который обертывает объект innerObject. Если innerObject удаляется из памяти by GC, этот объект WeakReference будет добавлен в queue.
WeakReference(T innerObject, ReferenceQueue<? super T> queue)
Например:
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
Далее нам нужен более сложный пример. В этом примере объекты Employee добавляются в Company. И объект List, содержащий список слабых ссылок на каждый объект Employee. Пока Company хранит объекты Employee, они не будут удалены из памяти by GC.
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 Basic
- Настройте java compiler для обработки вашего Annotation (Annotation Processing Tool)
- Программирование на Java для группы с помощью Eclipse и SVN
- Руководство Java WeakReference
- Руководство Java PhantomReference
- Сжатие и декомпрессия в Java
- Настройка Eclipse для использования JDK вместо JRE
- Методы String.format() и printf() в Java
- Синтаксис и новые функции в Java 8
- Регулярные выражения Java
- Руководство Java Multithreading Programming
- Библиотеки Java JDBC Driver для различных типов баз данных
- Руководство Java JDBC
- Получить значения столбцов, автоматически возрастающих при вставлении (Insert) записи, используя JDBC
- Руководство Java Stream
- Руководство Java Functional Interface
- Введение в Raspberry Pi
- Руководство Java Predicate
- Абстрактный класс и Interface в Java
- Модификатор доступа (Access modifiers) в Java
- Руководство Java Enum
- Руководство Java Annotation
- Сравнение и Сортировка в Java
- Руководство Java String, StringBuffer и StringBuilder
- Обработка исключений Java - Java Exception Handling
- Руководство Java Generics
- Манипулирование файлами и каталогами в Java
- Руководство Java BiPredicate
- Руководство Java Consumer
- Руководство Java BiConsumer
- Что мне нужно для начала работы с Java?
- История Java и разница между Oracle JDK и OpenJDK
- Установить Java в Windows
- Установите Java в Ubuntu
- Установите OpenJDK в Ubuntu
- Установить Eclipse
- Установите Eclipse в Ubuntu
- Быстрое изучение Java для начинающих
- История бит и байтов в информатике
- Типы данных в java
- Битовые операции
- Команда if else в Java
- команды switch в Java
- Циклы в Java
- Массивы (Array) в Java
- JDK Javadoc в формате CHM
- Наследование и полиморфизм в Java
- Руководство Java Function
- Руководство Java BiFunction
- Пример Java encoding и decoding с использованием Apache Base64
- Руководство Java Reflection
- Java Удаленный вызов методов - Java RMI
- Руководство Программирование Java Socket
- Какую платформу я должен выбрать для разработки приложений Java Desktop?
- Руководство Java Commons IO
- Руководство Java Commons Email
- Руководство Java Commons Logging
- Понимание Java System.identityHashCode, Object.hashCode и Object.equals
- Руководство Java SoftReference
- Руководство Java Supplier
- Аспектно-ориентированное программирование Java с помощью AspectJ (AOP)
Show More
- Руководства Java Servlet/JSP
- Руководства Java Collections Framework
- Java API для HTML, XML
- Руководства Java IO
- Руководства Java Date Time
- Руководства Spring Boot
- Руководства Maven
- Руководства Gradle
- Руководства Java Web Services
- Руководства Java SWT
- Руководства JavaFX
- Руководства Oracle Java ADF
- Руководства Struts2 Framework
- Руководства Spring Cloud