java:基于弱引用(WeakReference)的FunctionCached实现

作者注:走了弯路,guava缓存机制本就支持弱引用模式,参见新博客《guava:LoadingCache缓存机制支持弱引用(WeakReference)》

以前写过一篇博客《java:基于guava缓存(LoadingCache)实现结果缓存避免重复计算
提到我基于guava的缓存(com.google.common.cache.LoadingCache)实现结果计算结果缓存的类FunctionCached。它很好的解决了常量结果重复计算问题。
但最近我的应用场景有点变化。FunctionCached保存的结果有可能被多次重复使用,也有可能不再被继续使用。我希望这些不再被继续的使用数据能自动被回收,不要占用系统资源,如果万一它真的又被需要,就再次计算,并将结果缓存。
guava的缓存(com.google.common.cache.LoadingCache)的确可以清除闲置超时的对象,但它有个缺陷,只有在下次调用的时候,才会执行清除动作,如果无法预测是否有下次调用,那么有些闲置数据就永远没有机会清除。为解决这个问题我想到了弱引用(WeakReference)应该可以解决这个问题。
于是基于弱引用(WeakReference)在FunctionCached基础上我实现了FunctionCachedWeak类,使用弱引用定义数据,当需要读取数据而引用对象被回收时,重新计算并加入缓存。这样就能解决缓存中闲置数据占用资源的问题。

实现代码

实现代码如下:
FunctionCachedWeak.java,其将FunctionCached(https://gitee.com/l0km/common-java/blob/master/common-base2/src/main/java/net/gdface/utils/FunctionCachedWeak.java)作为成员对象.

import java.lang.ref.WeakReference;

import com.google.common.base.Function;
import com.google.common.cache.CacheBuilder;
/**
 * 基于{@link FunctionCached}实现弱引用的类型转转换接口{@link Function},
 * @author guyadong
 *
 * @param <K> 输入参数类型
 * @param <V> 输出参数类型
 * @see 2.9.3
 */
public class FunctionCachedWeak<K,V> implements Function<K, V>{
	private final Function<K, V> getterFunction;
	private final FunctionCached<K, WeakReference<V>> functionCached;
	private final V defaultValue;
	public FunctionCachedWeak(Function<K, V> getterFunction) {
		this(getterFunction, null);
	}
	public FunctionCachedWeak(Function<K, V> getterFunction,V defaultValue) {
		this.getterFunction = getterFunction;
		this.defaultValue = defaultValue;
		functionCached = FunctionCached.of (new AsWeakRef<>(getterFunction));
	}
	public V getUncached(K key) {
		return null == key ? defaultValue : getterFunction.apply(key);
	}

	public V get(K key) {
		WeakReference<V> weakRef = functionCached.get(key);
		if(null != weakRef) {
			if(weakRef.get() == null) {
				/** 弱引用失效时删除对应的key,重新计算 */
				System.out.println("reload");// 测试代码用于,弱引用失效时重新加载时显示
				functionCached.cache.asMap().remove(key);
				return get(key);
			}
			return weakRef.get();
		}
		return defaultValue;
	}
	/**
	 * 缓存调用
	 * @see #get(Object)
	 * @see com.google.common.base.Function#apply(java.lang.Object)
	 */
	@Override
	public V apply(K input) {
		return get(input);
	}
	/**
	 * 返回{@code getterFunction}的{@link FunctionCached}实例,
	 * 如果{@code getterFunction}为{@link FunctionCached}实例,则直接返回,否则创建新实例
	 * @param getterFunction
	 * @param defaultValue
	 * @see #of(Function, Object, CacheBuilder)
	 */
	public static <K, V> FunctionCachedWeak<K, V> of(Function<K, V> getterFunction,V defaultValue){
		if(getterFunction instanceof FunctionCachedWeak){
			return (FunctionCachedWeak<K, V>) getterFunction;
		}
		return new FunctionCachedWeak<K, V>(getterFunction, defaultValue); 
	}
	/**
	 * 返回{@code getterFunction}的{@link FunctionCached}实例(默认实例为{@code null})
	 * @param getterFunction
	 * @see #of(Function, Object)
	 */
	public static <K, V> FunctionCachedWeak<K, V> of(Function<K, V> getterFunction){
		return of(getterFunction,null); 
	}
	
	private static class AsWeakRef<K,V> implements Function<K, WeakReference<V>>{
		private final Function<K, V> getterFunction;
		public AsWeakRef(Function<K, V> getterFunction) {
			this.getterFunction = getterFunction;
		}
		@Override
		public WeakReference<V> apply(K input) {
			V v = getterFunction.apply(input);
			return null == v ? null : new WeakReference<>(v);
		}
		
	}
}

调用示例

调用示例:
FunctionCachedWeakTest.java

import org.junit.Test;

import com.google.common.base.Function;

public class FunctionCachedWeakTest {

	@Test
	public void testReload() throws InterruptedException {
		FunctionCachedWeak<Integer,String> functionCached = FunctionCachedWeak.of(new Function<Integer,String>() {

			@Override
			public String apply(Integer input) {
				return input.toString();
			}
		});
		for(int i=0;i<1000;++i) {
			functionCached.get(i);
		}
		System.gc(); // 显式调用垃圾收集器
		int count = 0;
		while(true) {
			System.out.printf("%s\n", functionCached.get(count++));
			Thread.sleep(1000);
			
		}
	}

}

完整代码参见码云仓库:https://gitee.com/l0km/common-java/blob/master/common-base2/src/main/java/net/gdface/utils/FunctionCachedWeak.java

测试代码:https://gitee.com/l0km/common-java/blob/master/common-base2/src/test/java/net/gdface/utils/FunctionCachedWeakTest.java

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值