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------------------------------------------> ");
		}
	}

}
时间: 2024-07-29 16:16:20

guava cache使用例子的相关文章

缓存框架Guava Cache部分源码分析

在本地缓存中,最常用的就是OSCache和谷歌的Guava Cache.其中OSCache在07年就停止维护了,但它仍然被广泛的使用.谷歌的Guava Cache也是一个非常优秀的本地缓存,使用起来非常灵活,功能也十分强大,可以说是当前本地缓存中最优秀的缓存框架之一.之前我们分析了OSCache的部分源码,本篇就通过Guava Cache的部分源码,来分析一下Guava Cache的实现原理. 在分析之前,先弄清数据结构的使用.之前的文章提到,OSCache使用了一个扩展的HashTable,作

第二章 Google guava cache源码解析1--构建缓存器

1.guava cache 当下最常用最简单的本地缓存 线程安全的本地缓存 类似于ConcurrentHashMap(或者说成就是一个ConcurrentHashMap,只是在其上多添加了一些功能) 2.使用实例 具体在实际中使用的例子,去查看<第七章 企业项目开发--本地缓存guava cache>,下面只列出测试实例: import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit;

(翻译)Google Guava Cache

翻译自Google Guava Cache This Post is a continuation of my series on Google Guava, this time covering Guava Cache. Guava Cache offers more flexibility and power than either a HashMap or ConcurrentHashMap, but is not as heavy as using EHCache or Memcache

Guava库学习:学习Guava Cache(六)CacheStats

原文地址:Guava库学习:学习Guava Cache(六)CacheStats 上一篇,Guava库学习:学习Guava Cache(五)CacheLoader 中, 我们学习了CacheLoader抽象类,主要是其中的from方法,接收一个Function或Supplier,返回一个CacheLoader实 例,至此,我们已经了解了如何创建一个强大的缓存机制,接下来,我们想要收集缓存执行或使用后的一些统计信息,又该怎么做呢?现在开始本篇,Guava Cache CacheStats的学习.

guava cache与spring集成

缓存的背景 缓存,在我们日常开发中是必不可少的一种解决性能问题的方法.简单的说,cache 就是为了提升系统性能而开辟的一块内存空间.在cpu进行计算的时候, 首先是读取寄存器,然后内存,再是硬盘.由于寄存器容量很小,不太适合存储我们需要快速读取的数据,放在硬盘中话,效率太低,所以大多数人将一些静态资源或者不经常修改的数据放在内存中. 缓存的作用 缓存的主要作用是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问使用.在日常开发的很多场合,由于受限于硬盘 IO的性能或者我们自身业务系统的数

google guava cache

老规矩,有些知识很容易忘记啊,还是记录一下咯. google guava cache中,有很多参数. 1.expireAfterAccess(n , timeunit)   表示cache中管理的key如果在n(s,m,h,d)时间范围内没有被使用,则被cache驱逐. 2.maximumSize(n)   表示可以缓存的最大数目.没有到达最大数目时, 即开始驱逐部门缓存数据. 3.removalListener     实现RemovalListener接口onRemoval方法.可以记录缓存

Guava学习笔记:Guava cache

缓存,在我们日常开发中是必不可少的一种解决性能问题的方法.简单的说,cache 就是为了提升系统性能而开辟的一块内存空间. 缓存的主要作用是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问使用.在日常开发的很多场合,由于受限于硬盘IO的性能或者我们自身业务系统的数据处理和获取可能非常费时,当我们发现我们的系统这个数据请求量很大的时候,频繁的IO和频繁的逻辑处理会导致硬盘和CPU资源的瓶颈出现.缓存的作用就是将这些来自不易的数据保存在内存中,当有其他线程或者客户端需要查询相同的数据资源时,

Guava库学习:学习Guava Cache知识汇总

原文地址:Guava库学习:学习Guava Cache知识汇总 至此,我们结束了对Guava Cache 缓存机制的学习,在学习过程中,我们学习了如何简单的通过MapMaker创建最简单的ConcurrentMap缓存,我们也了解了缓存的高级特性,以及强大的LoadingCache,我们也探索和学习了CacheBuilder.CacheLoader这些核心的API,以及CacheStats.RemovalLitener等,下面对这些文章做一些汇总,方便以后的查阅和复习.     Guava库学习

Java 高并发缓存与Guava Cache

一.背景 缓存是我们在开发中为了提高系统的性能,把经常的访问业务的数据第一次把处理结果先放到缓存中,第二次就不用在对相同的业务数据在重新处理一遍,这样就提高了系统的性能.缓存分好几种: (1)本地缓存. (2)数据库缓存. (3)分布式缓存. 分布式缓存比较常用的有memcached等,memcached是高性能的分布式内存缓存服务器,缓存业务处理结果,减少数据库访问次数和相同复杂逻辑处理的时间,以提高动态Web应用的速度. 提高可扩展性. 二.本地缓存在高并发下的问题以及解决 今天我们介绍的是