guava cache使用例子

关于介绍请参考:http://blog.csdn.net/liangrui1988/article/details/46120533#

下面是测试代码 ,下载源码可在github上获取:https://github.com/liangrui1988/guavaTest

package org.rui.test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

import org.junit.Test;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.Weigher;

/**
 *  Guava Cache有两种创建方式:
 * 
 *   1. cacheLoader   2. callable callback
 * 
 *   通过这两种方法创建的cache,和通常用map来缓存的做法比,不同在于,这两种方法都实现了一种逻辑——从缓存中取key
 * X的值,如果该值已经缓存过了,则返回缓存中的值
 * ,如果没有缓存过,可以通过某个方法来获取这个值。但不同的在于cacheloader的定义比较宽泛,是针对整个cache定义的
 * ,可以认为是统一的根据key值load value的方法。而callable的方式较为灵活,允许你在get的时候指定。
 * 
 * @author liangrui
 *
 */
public class Tests
{

	/**
	 * CacheLoader
	 */
	@Test
	public void loadingCache()
	{
		LoadingCache<String, String> graphs = CacheBuilder.newBuilder()
				.maximumSize(1000).build(new CacheLoader<String, String>()
				{
					@Override
					public String load(String key) throws Exception
					{
						System.out.println("key:"+key);
						if("key".equals(key)){
							return "key return result";
						}else{
							return "get-if-absent-compute";
						}
						
						
					}

				});

		String resultVal = null;
		try {
			resultVal = graphs.get("key");
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		
		System.out.println(resultVal);
	}

	/**
	 * 
	 * Callable
	 * 在使用缓存前,首先问自己一个问题:有没有合理的默认方法来加载或计算与键关联的值?如果有的话,你应当使用CacheLoader。如果没有,
	 * 或者你想要覆盖默认的加载运算,同时保留"获取缓存-如果没有-则计算"[get-if-absent-compute]的原子语义,
	 * 你应该在调用get时传入一个Callable实例
	 * 。缓存元素也可以通过Cache.put方法直接插入,但自动加载是首选的,因为它可以更容易地推断所有缓存内容的一致性。
	 */
	@Test
	public void callablex() throws ExecutionException
	{

		Cache<String, String> cache = CacheBuilder.newBuilder()
				.maximumSize(1000).build();

		String result = cache.get("key", new Callable<String>()
		{
			public String call()
			{
				return "result";
			}
		});
		System.out.println(result);
	}

	/**
	 * 从LoadingCache查询的正规方式是使用get(K)方法。这个方法要么返回已经缓存的值,要么使用CacheLoader向缓存原子地加载新值。
	 * 由于CacheLoader可能抛出异常,LoadingCache.get(K)也声明为抛出ExecutionException异常。
	 * 如果你定义的CacheLoader没有声明任何检查型异常
	 * ,则可以通过getUnchecked(K)查找缓存;但必须注意,一旦CacheLoader声明了检查型异常
	 * ,就不可以调用getUnchecked(K)。
	 * 
	 * @throws ExecutionException
	 */
	@Test
	public void capacity()
	{
		LoadingCache<String, String> graphs = CacheBuilder.newBuilder()
				.maximumWeight(100000).weigher(new Weigher<String, String>()
				{
					public int weigh(String k, String g)
					{
						return 100;
					}
				}).build(new CacheLoader<String, String>()
				{
					public String load(String key)
					{ // no checked exception
						// return createExpensiveGraph(key);
						return "xxxx";
					}
				});

	}
}

package org.rui.test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import org.junit.Test;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheStats;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import com.google.common.cache.Weigher;

/**
 * cache的参数说明:
 * 
 *   回收的参数:   1. 大小的设置:CacheBuilder.maximumSize(long)
 * CacheBuilder.weigher(Weigher) CacheBuilder.maxumumWeigher(long)   2.
 * 时间:expireAfterAccess(long, TimeUnit) expireAfterWrite(long, TimeUnit)   3.
 * 引用:CacheBuilder.weakKeys() CacheBuilder.weakValues()
 * CacheBuilder.softValues()   4. 明确的删除:invalidate(key) invalidateAll(keys)
 * invalidateAll()   5. 删除监听器:CacheBuilder.removalListener(RemovalListener)   
 * 
 *   refresh机制:   1. LoadingCache.refresh(K) 在生成新的value的时候,旧的value依然会被使用。   2.
 * CacheLoader.reload(K, V) 生成新的value过程中允许使用旧的value   3.
 * CacheBuilder.refreshAfterWrite(long, TimeUnit) 自动刷新cache
 *
 *
 */
public class Eviction
{

	/**
	 * 基于容量的回收
	 *
	 *
	 * maximumSize(1) 缓存将尝试回收最近没有使用或总体上很少使用的缓存项
	 * 
	 * 不同的缓存项有不同的“权重”(weights)——例如,如果你的缓存值
	 * ,占据完全不同的内存空间,你可以使用CacheBuilder.weigher(Weigher)指定一个权重函数
	 * 
	 */

	@Test
	public void callablex() throws ExecutionException, InterruptedException
	{
		// .maximumSize(100)
		Cache<String, User2> cache = CacheBuilder.newBuilder().maximumWeight(5)
				.weigher(new Weigher<String, User2>()
				{
					@Override
					public int weigh(String arg0, User2 user)
					{
						return 3;
					}
				}).removalListener(new RemovalListener<String, User2>()
				{
					@Override
					public void onRemoval(RemovalNotification<String, User2> rn)
					{
						System.out.println(rn.getKey() + "==被移除");
					}

				}).build();

		User2 result = cache.get("key", new Callable<User2>()
		{
			public User2 call()
			{
				return new User(1, "liang");
			}
		});

		// Thread.sleep(10000);

		User result2 = (User) cache.get("key2", new Callable<User2>()
		{
			public User2 call()
			{
				return new User(2, "liang2");
			}
		});

		User result3 = (User) cache.get("key3", new Callable<User>()
		{
			public User call()
			{
				return new User(3, "liang3");
			}
		});

		System.out.println(result);
		System.out.println(result2);
		System.out.println(result3);
		System.out.println(cache.size());
	}

	/**
	 * 
	 * 
	 * 定时回收(Timed Eviction) expireAfterAccess(long,
	 * TimeUnit):缓存项在给定时间内没有被读/写访问,则回收。请注意这种缓存的回收顺序和基于大小回收一样。
	 * expireAfterWrite(long,
	 * TimeUnit):缓存项在给定时间内没有被写访问(创建或覆盖),则回收。如果认为缓存数据总是在固定时候后变得陈旧不可用,这种回收方式是可取的。
	 * 
	 * 
	 * 
	 * // .expireAfterWrite(5, TimeUnit.SECONDS)//给定时间内没有写访问,则回收。 27 //
	 * .expireAfterAccess(3, TimeUnit.SECONDS)// 缓存过期时间为3秒
	 * 
	 * @param args
	 */

	Cache<String, User2> cache2 = CacheBuilder.newBuilder().maximumSize(100)
			.expireAfterWrite(3, TimeUnit.MILLISECONDS)
			// .expireAfterAccess(3000, TimeUnit.MILLISECONDS)
			.removalListener(new RemovalListener<String, User2>()
			{
				@Override
				public void onRemoval(RemovalNotification<String, User2> rn)
				{
					System.out.println("Cause:" + rn.getCause() + " k: "
							+ rn.getKey() + " v :" + rn.getValue() + "==被移除");
				}

			}).build();

	@Test
	public void timerEvication() throws ExecutionException,
			InterruptedException
	{

		User2 user = cache2.get("k1", new Callable<User2>()
		{
			@Override
			public User2 call() throws Exception
			{

				return new User(100, "hello");
			}
		});
		Thread.sleep(8000);
		System.out.println(cache2.size());

		User2 user2 = cache2.get("k2", new Callable<User2>()
		{
			@Override
			public User2 call() throws Exception
			{

				return new User(200, "hello2");
			}
		});
		System.out.println(user);
		Thread.sleep(8000);
		user = cache2.get("k1", new Callable<User2>()
		{
			@Override
			public User2 call() throws Exception
			{

				return new User(10000000, "k1k1k1k1k1k1k1");
			}
		});

		System.out.println(cache2.size());

		User2 user3 = cache2.get("k3", new Callable<User2>()
		{
			@Override
			public User2 call() throws Exception
			{

				return new User(300, "hello3");
			}
		});

		System.out.println(user);
		System.out.println(user2);
		System.out.println(user3);

		Thread.sleep(10000);
		System.out.println(cache2.size());
		CacheStats status = cache2.stats();
		status.missCount();

	}

	/**
	 * 显式清除
	 * 
	 * 任何时候,你都可以显式地清除缓存项,而不是等到它被回收:
	 * 
	 * 个别清除:Cache.invalidate(key) 批量清除:Cache.invalidateAll(keys)
	 * 清除所有缓存项:Cache.invalidateAll()
	 * 
	 * @param args
	 */

	Cache<String, User2> cache3 = CacheBuilder.newBuilder().maximumSize(100)
			.removalListener(new RemovalListener<String, User2>()
			{
				@Override
				public void onRemoval(RemovalNotification<String, User2> rn)
				{
					System.out.println("Cause:" + rn.getCause() + " k: "
							+ rn.getKey() + " v :" + rn.getValue() + "==被移除");
				}

			}).build();

	@Test
	public void clear() throws ExecutionException
	{

		User2 u = cache3.get("u1", new Callable<User2>()
		{
			@Override
			public User2 call() throws Exception
			{
				System.out.println("exec call>>>return result");
				return new User(500, "world");
			}
		});

		System.out.println(u);

		u = cache3.get("u1", new Callable<User2>()
		{
			@Override
			public User2 call() throws Exception
			{
				System.out.println("exec call>>>return result");
				return new User(500, "world");
			}
		});
		System.out.println(u);
		cache3.invalidate("u1");
		u = cache3.get("u1", new Callable<User2>()
		{
			@Override
			public User2 call() throws Exception
			{
				System.out.println("exec call>>>return result");
				return new User(500, "world");
			}
		});
		
		
		
		
	}

}

package org.rui.test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListenableFutureTask;

/**
 * 刷新和回收不太一样。正如LoadingCache.refresh(K)所声明,刷新表示为键加载新值,这个过程可以是异步的。在刷新操作进行时,
 * 缓存仍然可以向其他线程返回旧值,而不像回收操作,读缓存的线程必须等待新值加载完成。
 * 
 * 如果刷新过程抛出异常,缓存将保留旧值,而异常会在记录到日志后被丢弃
 * 
 * @author lenovo
 *
 */
public class Refresh
{

	static int ixs = 0;

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

		LoadingCache<String, String> graphs = CacheBuilder.newBuilder()
				.maximumSize(1000).refreshAfterWrite(1, TimeUnit.MICROSECONDS)
				.build(new CacheLoader<String, String>()
				{
					@Override
					public ListenableFuture<String> reload(final String key,
							String oldValue) throws Exception
					{
						System.out.println("oldValue:" + oldValue);
						ixs++;
						if (key.equals("keyx")) {
							return Futures.immediateFuture("new Values_" + ixs);
						} else {

							ListenableFutureTask<String> taks = ListenableFutureTask
									.create(new Callable<String>()
									{
										@Override
										public String call() throws Exception
										{
											return key + " xxxxxx_" + ixs;
										}
									});
							Executor executor = new ExecutorImple();
							executor.execute(taks);
							return taks;
						}

					}

					@Override
					public String load(String arg0) throws Exception
					{
						return "get-if-absent-compute_" + ixs;
					}

				});

		String resultVal = null;

		resultVal = graphs.get("key");

		System.out.println(resultVal);
		Thread.sleep(2000);
		resultVal = graphs.get("key");
		System.out.println(resultVal);
		Thread.sleep(2000);
		resultVal = graphs.get("key");
		System.out.println(resultVal);
		Thread.sleep(5000);
		resultVal = graphs.get("key");
		System.out.println(resultVal);
	}
}

package org.rui.test;

import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

import org.junit.Test;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheStats;

/**
 * 统计 信息
 * 
 * @author lenovo
 *
 */
public class RecordStatus
{
	Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(2)
			.recordStats().build();

	@Test
	public void loadCached() throws ExecutionException
	{
		String result = cache.get("key", new Callable<String>()
		{
			public String call()
			{
				return "result";
			}
		});

		String result2 = cache.get("key2", new Callable<String>()
		{
			public String call()
			{
				return "result2";
			}
		});

		String result3 = cache.get("key3", new Callable<String>()
		{
			public String call()
			{
				return "result3";
			}
		});

		result = cache.get("key", new Callable<String>()
		{
			public String call()
			{
				return "result";
			}
		});

		System.out.println(result);
		System.out.println(result2);
		System.out.println(result3);
		System.out.println(cache.getIfPresent("key"));

		//
		CacheStats cstats = cache.stats();
		System.out.println("loadCount:" + cstats.loadCount()
				+ "  loadSuccessCount: " + cstats.loadSuccessCount());

		System.out.println("缓存命中率:" + cstats.hitRate() + " hitCount: "
				+ cstats.hitCount());// 缓存命中率;
		System.out.println("加载新值的平均时间:" + cstats.averageLoadPenalty() + " 纳秒");// 加载新值的平均时间,单位为纳秒;
		System.out.println("缓存项被回收的总数:" + cstats.evictionCount());// 缓存项被回收的总数,不包括显式清除。
		System.out.println();

		// cache.asMap().entrySet()
		Set<String> set = cache.asMap().keySet();// 所有健
		Iterator<String> it = set.iterator();
		System.out.println("all key====");
		while (it.hasNext()) {

			System.out.print(it.next() + " \t ");
		}
		System.out.println();

	}

}

下面是本人自已的想法,还没正实可用性,仅参考





package org.rui.utils;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

import com.google.common.cache.Cache;

/**
 * guava cached 共公接口
 * 
 * @author liangrui
 * @date 2015/6/7
 * @param <K>
 * @param <V>
 */
public interface ICached<K, V>
{
	/**
	 * callable 获取cached 方式
	 * 
	 * @param key
	 * @param callable
	 * @return
	 * @throws ExecutionException
	 */
	V getCallable(K key, Callable<V> callable) throws ExecutionException;

	/**
	 * cachedLoader 获取方式
	 * 
	 * @param key
	 * @return
	 * @throws ExecutionException
	 */
	V getLoader(K key) throws ExecutionException;

	/**
	 * 获取某一项的 缓存
	 * 
	 * @param Cached
	 * @return
	 */
	Cache getCache(String Cached);

	/**
	 * 获取所有guava 缓存
	 * 
	 * @return
	 */
	Cache[] getCache();

}


package org.rui.utils;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

/**
 * 方便统一管理缓存 关于配置可根据系统实际情况配置
 * 
 * @date 2015/6/7
 * @author liangrui
 *
 */
public class GuavaCachedImpl implements ICached<String, Object>
{
	/*** cached 缓存最大数量 **/
	public static final Integer CACHE_MAXIMUMSIZE = 10000;//
	/** loaderCached 缓存最大数量 **/
	public static final Integer LOADING_CACHE_MAXIMUMSIZE = 10000;
	/*** 缓存项在给定时间内没有被写访问(创建或覆盖),则回收 **/
	public static final Integer EXPIRE_AFTER_WRITE_MILLISECONDS = 1000;

	private Cache<String, Object> cache = CacheBuilder
			.newBuilder()
			.maximumSize(CACHE_MAXIMUMSIZE)
			.expireAfterWrite(EXPIRE_AFTER_WRITE_MILLISECONDS,
					TimeUnit.MILLISECONDS).recordStats().build();

	private LoadingCache<String, Object> loadingCached = CacheBuilder
			.newBuilder()
			.maximumSize(LOADING_CACHE_MAXIMUMSIZE)
			.expireAfterWrite(EXPIRE_AFTER_WRITE_MILLISECONDS,
					TimeUnit.MILLISECONDS)
			.build(new CacheLoader<String, Object>()
			{
				@Override
				public String load(String key) throws Exception
				{
					System.out.println("key:" + key);
					if ("key".equals(key)) {
						return "key return result";
					} else {
						return "get-if-absent-compute";
					}

				}

			});

	@Override
	public Object getCallable(String key, Callable<Object> callable)
			throws ExecutionException
	{
		Object value = cache.get(key, callable);
		return value;
	}

	@Override
	public Object getLoader(String key) throws ExecutionException
	{
		return loadingCached.get(key);
	}

	@Override
	public Cache getCache(String cahced)
	{
		if ("cache".equals(cahced)) {
			return cache;
		}
		if ("loadingCached".equals(cahced)) {
			return loadingCached;
		} else {

		}
		return null;
	}

	@Override
	public Cache[] getCache()
	{
		Cache[] cacheArray = new Cache[]
		{ cache, loadingCached };

		return cacheArray;
	}

}

package org.rui.utils;

import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheStats;

/**
 * cache 测试
 * 
 * @author lenovo
 *
 */
public class Main
{

	public static void main(String[] args) throws ExecutionException
	{
		ICached<String, Object> cached = new GuavaCachedImpl();

		Object result = cached.getCallable("key1", new Callable<Object>()
		{
			@Override
			public Object call() throws Exception
			{
				return "|cached value|";
			}
		});

		System.out.println(cached.getLoader("key"));
		System.out.println(result);

		printStats(cached.getCache());

	}

	/**
	 * 打印缓存状态信息
	 * 
	 * @param caches
	 */
	public static void printStats(Cache[] caches)
	{

		System.out.println("打印缓存状态信息");
		for (Cache cache : caches) {
			System.out.println();
			System.out
					.println("start------------------------------------------> ");
			System.out.println("loadCount:" + cache.stats().loadCount()
					+ "  loadSsuccessCount: "
					+ cache.stats().loadSuccessCount());

			System.out.println("缓存命中率:" + cache.stats().hitRate()
					+ " hitCount: " + cache.stats().hitCount());// 缓存命中率;
			System.out.println("加载新值的平均时间:"
					+ cache.stats().averageLoadPenalty() + " 纳秒");// 加载新值的平均时间,单位为纳秒;
			System.out.println("缓存项被回收的总数:" + cache.stats().evictionCount());// 缓存项被回收的总数,不包括显式清除。
			System.out.println();

			System.out.println();
			System.out.println("cached 健和值 ===============");

			Set setEn = cache.asMap().entrySet();
			Iterator<Object> it = setEn.iterator();
			System.out.println();
			System.out.println("all entrySet====>");
			while (it.hasNext()) {
				System.out.print(it.next() + " \t ");
			}

			System.out.println();
			System.out.println();
			Set<String> set = cache.asMap().keySet();// 所有健
			Iterator<String> it2 = set.iterator();
			System.out.println("all key====>");
			while (it2.hasNext()) {
				System.out.print(it2.next() + " \t ");
			}
			System.out.println();
			System.out
					.println("end------------------------------------------> ");
		}
	}

}


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。