guava cache

缓存,在我们日常开发中是必不可少的一种解决性能问题的方法。简单的说,cache 就是为了提升系统性能而开辟的一块内存空间。

  缓存的主要作用是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问使用。在日常开发的很多场合,由于受限于硬盘IO的性能或者我们自身业务系统的数据处理和获取可能非常费时,当我们发现我们的系统这个数据请求量很大的时候,频繁的IO和频繁的逻辑处理会导致硬盘和CPU资源的瓶颈出现。缓存的作用就是将这些来自不易的数据保存在内存中,当有其他线程或者客户端需要查询相同的数据资源时,直接从缓存的内存块中返回数据,这样不但可以提高系统的响应时间,同时也可以节省对这些数据的处理流程的资源消耗,整体上来说,系统性能会有大大的提升。

  缓存在很多系统和架构中都用广泛的应用,例如:

  1.CPU缓存
  2.操作系统缓存
  3.本地缓存
  4.分布式缓存
  5.HTTP缓存
  6.数据库缓存
  等等,可以说在计算机和网络领域,缓存无处不在。可以这么说,只要有硬件性能不对等,涉及到网络传输的地方都会有缓存的身影。

  Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。整体上来说Guava cache 是本地缓存的不二之选,简单易用,性能好。

  Guava Cache有两种创建方式:

  1. cacheLoader
  2. callable callback

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

 

-----------------------------------------------------

涉及线程安全, HashMap, 缓存等.

场景比如: Lazy initialization或Caching.

要对每一个需要用到的员工名字通过数据库查询她一年以来的加班多少, 绩效等等各种数据, 经过一系列步骤计算出员工的奖金数额.

这个东西算起来太费资源, 那么, 就要延迟计算, 只有员工主动跑来要加薪, 才去算. 而且要缓存, 如果这个员工对只发50元奖金心存不满, 反复来吵闹, 甚至投诉, 就不用重新计算.

自己写怎么写呢? 假设我那个算奖金的函数写好了, 就叫compute(name):

classBonusManager{privatestaticfinalMap<String,Integer> cache =newHashMap<String,Integer>();publicstaticInteger getBonus(String name){Integer bonus = cache.get(name);if(bonus ==null){
            bonus = compute(name);// 危险在这里!多线程安全问题!}
      cache.put(name, bonus);return bonus;}privateInteger compute(String name){// 根据员工名字做一系列计算奖金的工作, 很费时}}

这里用HashMap实现了缓存, 但问题的关键是上面的代码不是线程安全的.

可以在getBonus()上面加一个synchronized关键字, 然后它就线程安全了. 但是,如果需要极高极高的并发能力呢?

可能会想到把HashMap改成ConcurrentHashMap.

近了一步了, 但是还不完全. 这是因为两个线程可能同时执行if (bonus == null)然后同时去运行compute(). 结果是, 可能对某些名字重复运行compute(). 还是不完美.

此时, 如果想到了双检查锁定机制(double-checked locking), 那就没招了.

但是, 单例模式请不要用double-checked locking, 相见这里.

遇到这种情况, 可以使用Google Guava中的LoadingCache, 之前的Guava版本利用MapMaker中的makeComputingMap()方法.

参考LoadingCache, CacheBuilder, CacheLoader类.

publicclassBonusManager{privatestaticLoadingCache<String,Integer> cache =CacheBuilder.newBuilder().maximumSize(1000)// 最多可以缓存1000个key.expireAfterWrite(10,TimeUnit.MINUTES)// 过期时间.build(newCacheLoader<String,Integer>(){publicInteger load(String key){return compute(key);// DOTO}});privatestaticInteger compute(String name){// 一些列复杂的计算过程}}

可把LoadingCache看作一个线程安全的Map.

使用时可以这样:

int bonus = cache.get("zhangsan");
时间: 2024-09-17 04:13:52

guava cache的相关文章

Java Cache系列之Guava Cache实现详解

Guava作为Google开源出来的工具库,Google自己对Guava的描述:The Guava project contains several of Google's core libraries that we rely on in our Java-based projects: collections, caching, primitives support, concurrency libraries, common annotations, string processing,

guava翻译系列之Cache

Guava Cache 在软件开发的过程,缓存是一个非常重要的话题. 在稍微复杂的开发过程中,我们基本上是不可能不使用到缓存的. 至少我们会使用Map去存储一些东西. 这其实就是一个最简单的缓存. Guava给我们提供了比简单的使用HashMap更强大更灵活的功能,但是和专业的缓存工具相比,(EHCache,Memcached)功能还有些不足, 那么这一章,我们将覆盖Guava cache的下面几个方面: -- 使用MapMaker类创建ConcurrentMap实例 -- 使用CacheBui

Google的Java常用类库 Guava

Guava 中文是石榴的意思,该项目是 Google 的一个开源项目,包含许多 Google 核心的 Java 常用库. 1. 基本工具 [Basic utilities] 让使用Java语言变得更舒适 1.1 使用和避免null:null是模棱两可的,会引起令人困惑的错误,有些时候它让人很不舒服.很多Guava工具类用快速失败拒绝null值,而不是盲目地接受 1.2 前置条件: 让方法中的条件检查更简单 1.3 常见Object方法: 简化Object方法实现,如hashCode()和toSt

Spring Cache 介绍

Spring Cache 缓存是实际工作中非常常用的一种提高性能的方法, 我们会在许多场景下来使用缓存. 本文通过一个简单的例子进行展开,通过对比我们原来的自定义缓存和 spring 的基于注释的 cache 配置方法,展现了 spring cache 的强大之处,然后介绍了其基本的原理,扩展点和使用场景的限制.通过阅读本文,你应该可以短时间内掌握 spring 带来的强大缓存技术,在很少的配置下即可给既有代码提供缓存能力. 概述 Spring 3.1 引入了激动人心的基于注释(annotati

Google Guava官方教程(中文版)

原文链接  译文链接 译者: 沈义扬,罗立树,何一昕,武祖  校对:方腾飞 引言 Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] .缓存 [caching] .原生类型支持 [primitives support] .并发库 [concurrency libraries] .通用注解 [common annotations] .字符串处理 [string processing] .I/O 等等. 所有这些工具每天都在被Google

Guava - 并行编程Futures详解_java

Guava为Java并行编程Future提供了很多有用扩展,其主要接口为ListenableFuture,并借助于Futures静态扩展. 继承至Future的ListenableFuture,允许我们添加回调函数在线程运算完成时返回值或者方法执行完成立即返回. 对ListenableFuture添加回调函数: Futures.addCallback(ListenableFuture<V>, FutureCallback<V>, Executor) 其中 FutureCallbac

[Google Guava] 3-缓存

原文地址  译文地址    译者:许巧辉  校对:沈义扬 范例 01 LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder() 02         .maximumSize(1000) 03         .expireAfterWrite(10, TimeUnit.MINUTES) 04         .removalListener(MY_LISTENER) 05         .build( 06           

Linkedin工程师是如何优化他们的Java代码的(转)

  英文原文:LinkedIn Feed: Faster with Less JVM Garbage 最近在刷各大公司的技术博客的时候,我在Linkedin的技术博客上面发现了一篇很不错博文.这篇博文介绍了Linkedin信息流中间层Feed Mixer,它为Linkedin的Web主页,大学主页,公司主页以及客户端等多个分发渠道提供支撑(如下图所示). 在Feed Mixer里面用到了一个叫做SPR(念"super")的库.博文讲的就是如何优化SPR的java代码.下面就是他们总结的

数据-缓存漫谈

注:本文不涉及系统的技术实现细节 一.缓存特性以及应用场景 数据对互联网而言并不陌生,甚至是每天都需要打交道的部分,根据不同的行业不同的业务,都有不同的数据,而但凡规模增大到一定程度,即使分类后的数据也会庞大到一定的数量级. 几百-几万-几百万-亿级别的数据. 当数据量到达一个数量级之后,如何快速检索到用户需要的数据乃至经历过一层层数据逻辑筛选后最终吐露给用户所需的耗时也是开发者需要考虑的问题了. 与数据库访问优化漏斗法则相似,数据的访问优化也在大体上遵循类似的法则. 减少数据访问 返回更少数据