Java中的弱引用(WeakReference)是用来描述那些不会影响对象生命周期,但可能会在任何时候被垃圾收集器回收的对象引用。弱引用通常用于描述那些对象,它们非常重要,但又允许被自动回收。
在现实应用场景中,有些数据我们一开始会在初始时使用,之后使用的频率会很低,但它又比较大。如果使用普通的引用,会常驻内存占用资源。这时弱引用就派上用场了。
所以我们可以实现一个Supplier接口的类,封装一个弱引用实例。当要读取实例时,如果弱引用指向的实例不为null时就返回这个实例,当弱引用指向的对象为null时,执行加载,再返回。这样,就可以实现类似懒加载的方式按需获取数据,当数据不再被需要时,由GC自动回收。
基本实例逻辑的伪代码差不多就是这样:
public T get() {
if(null == weakReference) {
synchronized (this) {
if(null == weakReference) {
// 当弱引用对象为null时 执行加载实例
weakReference =....;
}
}
}
if(null == weakReference.get()){
// 当弱引用指向的对象为null时,执行加载
// 加载实例
weakReference =....;
}
return weakReference.get();
}
为了方便使用,我将这个逻辑封装了一个实现Supplier接口的WeakSupplier类。
实现代码
WeakSupplier.java
import java.lang.ref.WeakReference;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* {@link Supplier}弱引用实现,当弱引用失效时重新执行加载
* @author guyadong
*
* @param <T>
* @see 2.9.3
*/
public class WeakSupplier<T> implements Supplier<T> {
private final Supplier<T> supplier;
private volatile WeakReference<T> weakReference;
/**
* @param supplier
* @param immediateLoading 是否立即加载,为{@code true}立即调用 supplier
*/
public WeakSupplier(Supplier<T> supplier, boolean immediateLoading) {
this.supplier = checkNotNull(supplier,"supplier is null");
if(immediateLoading) {
doGet();
}
}
public WeakSupplier(Supplier<T> supplier) {
this(supplier, true);
}
private void doGet() {
weakReference = new WeakReference<>(checkNotNull(supplier.get(),"value from supplier %s is null",supplier));
}
@Override
public T get() {
if(null == weakReference) {
synchronized (this) {
if(null == weakReference) {
doGet();
}
}
}
if(null == weakReference.get()){
System.out.println("reload");
doGet();
}
return weakReference.get();
}
/**
* 创建{@link WeakSupplier}实例
* @param <T>
* @param supplier
* @param immediateLoading 是否立即加载,为{@code true}立即调用 supplier
*/
public static <T> WeakSupplier<T> of(Supplier<T> supplier,boolean immediateLoading){
if(supplier instanceof WeakSupplier) {
return (WeakSupplier<T>) supplier;
}
return new WeakSupplier<>(supplier, immediateLoading);
}
/**
* 创建{@link WeakSupplier}实例(立即加载)
* @param <T>
* @param supplier
*/
public static <T> WeakSupplier<T> of(Supplier<T> supplier){
return of(supplier,true);
}
public static<T> Function<Supplier<T>, WeakSupplier<T>> weakSupplierFun(){
return new Function<Supplier<T>, WeakSupplier<T>>(){
@Override
public WeakSupplier<T> apply(Supplier<T> input) {
return of(input);
}};
}
}
单元测试及调用示例
WeakSupplierTest.java
import java.util.List;
import java.util.ArrayList;
import org.junit.Test;
import com.google.common.base.Supplier;
public class WeakSupplierTest {
@Test
public void testReload() throws InterruptedException {
List<WeakSupplier<String>> suppliers = new ArrayList<>();
for(int i=0;i<1000;++i) {
final int num = i;
suppliers.add(WeakSupplier.of(new Supplier<String>() {
@Override
public String get() {
return "!!!!WEAK COUNT!!!!:"+ num;
}
}));
}
System.gc(); // 显式调用垃圾收集器
int count = 0;
while(count<suppliers.size()) {
System.out.printf("%s\n", suppliers.get(count++).get());
Thread.sleep(1000);
}
}
}
完整代码参见码云仓库:https://gitee.com/l0km/common-java/blob/master/common-base2/src/main/java/net/gdface/utils/WeakSupplier.java
测试代码:https://gitee.com/l0km/common-java/blob/master/common-base2/src/test/java/net/gdface/utils/WeakSupplierTest.java