`

google的ConcurrentLinkedHashmap源代码解析

LRU 
阅读更多
原文地址:http://janeky.iteye.com/blog/1534352
简述
ConcurrentLinkedHashMap 是google团队提供的一个容器。它有什么用呢?其实它本身是对

ConcurrentHashMap的封装,可以用来实现一个基于LRU策略的缓存。详细介绍可以参见

http://code.google.com/p/concurrentlinkedhashmap

使用范例
Java代码  收藏代码
public static void main(String[] args) { 
ConcurrentLinkedHashMap<Integer, Integer> map = new  
<span style="white-space: pre;">    </span>ConcurrentLinkedHashMap.Builder<Integer,Integer>().maximumWeightedCapacity(2). 
Java代码  收藏代码
weigher(Weighers.singleton()).build(); 
Java代码  收藏代码
map.put(1, 1); 
map.put(2, 2); 
map.put(3, 3); 
System.out.println(map.get(1));//null 已经失效了 
System.out.println(map.get(2)); 

ConcurrentLinkedHashMap 的构造函数比较特殊,它采用了Builder(构造器,GOF模式之一)。

它本身也是实现了ConcurrentMap接口的,所以使用起来跟ConcurrentHashMap一样。我们先put

进去三个元素,然后获取第一个元素,果然是null,因为基于LRU(最近使用)算法,key=1的节

点已经失效了。

源代码解析
先来看看它的整体框架


它本质是额外维护了一个双向链表,每次读和写都要改变相应节点的位置,将其移至队列头。

什么时候判断容易已经满了,是根据weight。每个元素都有一个weight,每增加一个元素,weight累计。当达到最大值的时候,就需要剔除最少操作的那个元素了,并且触发相关的事件。

我们先来看put函数

Java代码  收藏代码
V put(K key, V value, boolean onlyIfAbsent) { 
    checkNotNull(value); 
 
    final int weight = weigher.weightOf(key, value);//计算weight 
    final WeightedValue<V> weightedValue = new WeightedValue<V>(value, weight); 
    final Node node = new Node(key, weightedValue);//对数据进行包装,准备存入 
 
ConcurrentHashMap 
 
    for (;;) { 
      final Node prior = data.putIfAbsent(node.key, node); 
      if (prior == null) {//这个key之前没有值 
        afterCompletion(new AddTask(node, weight));//更新后续操作 
        return null; 
      } else if (onlyIfAbsent) { 
        afterCompletion(new ReadTask(prior)); 
        return prior.getValue(); 
      } 

AddTask 是判断是否容量满了,需要剔除其他元素
Java代码  收藏代码
final class AddTask extends AbstractTask { 
    final Node node; 
    final int weight; 
 
    @Override 
    @GuardedBy("evictionLock") 
    public void run() { 
      weightedSize += weight; 
 
      // ignore out-of-order write operations 
      if (node.get().isAlive()) { 
        evictionDeque.add(node); 
        evict();//是否移除失效的 
      } 
    } 
 
  } 
 
void evict() { 
    
    while (hasOverflowed()) { 
      Node node = evictionDeque.poll(); 
 
      // If weighted values are used, then the pending operations will adjust 
      // the size to reflect the correct weight 
      if (node == null) { 
        return; 
      } 
 
      // Notify the listener only if the entry was evicted 
      if (data.remove(node.key, node)) {//移除失效的 
        pendingNotifications.add(node); 
      } 
 
      node.makeDead(); 
    } 
  } 

get函数更简单一点,只是将这个key节点移至队列头
Java代码  收藏代码
public V get(Object key) { 
    final Node node = data.get(key); 
    if (node == null) { 
      return null; 
    } 
    afterCompletion(new ReadTask(node)); 
    return node.getValue(); 
  } 

性能比较 vs ConcurrentHashMap
不用说了,肯定是ConcurrentHashMap要好一点了,因为本文的主角还要维护一个操作队列嘛:)
不过性能上不是差很多,见下图。


总结:
利用ConcurrentLinkedHashMap来做基于LRU的缓存,还是值得推荐的。我们可以定义它的容器大小,基于LRU,就可以保证较高的命中率了。

参考资料:
http://code.google.com/p/concurrentlinkedhashmap
分享到:
评论

相关推荐

    google搜搜 源代码

    【标签】"google搜搜 源代码"再次确认了该压缩包的内容,意味着它包含的文件与Google搜索引擎的源代码有关,可能是仿造的、修改的,或者是对原版Google搜索算法的解析或实现。 【压缩包子文件的文件名称列表】: 1....

    google protobuf 最新源代码

    google protobuf 最新源代码google protobuf 最新源代码google protobuf 最新源代码google protobuf 最新源代码google protobuf 最新源代码google protobuf 最新源代码google protobuf 最新源代码google protobuf ...

    提取网页源代码

    5. **Web API**:一些服务提供API接口,可以直接获取网页源代码,例如Google的Custom Search JSON API。 正确解析网页源代码,需要理解HTML的基本结构和语法规则。HTML由一系列标签组成,每个标签都有开始和结束...

    谷歌小恐龙HTML源代码

    谷歌小恐龙HTML源代码

    查看网页源代码查看网页源代码

    在大多数现代浏览器中,如Google Chrome、Firefox、Microsoft Edge或Safari,你可以通过以下步骤来查看源代码: 1. 打开你想要查看源代码的网页。 2. 右键点击页面,选择“查看网页源代码”或“审查元素”(Inspect...

    caffe源代码解析

    Blob的源代码解析可以从以下几个方面展开: 1. 数据存储:Blob内部有两个成员变量`data_`和`diff_`,它们分别指向实际存储数据和梯度的内存区域。这两个指针可能指向`SyncedMemory`对象,这是一个管理内存分配和CPU...

    谷歌小恐龙彩蛋源代码

    总的来说,谷歌小恐龙彩蛋源代码的学习可以提供丰富的编程经验,涵盖网页开发的基础和高级概念,如DOM操作、动画制作、事件处理、以及游戏逻辑设计等。无论是对于初学者还是有经验的开发者,这都是一份有价值的参考...

    google 标准的图像浏览器源代码

    在深入探讨Google标准图像浏览器源代码之前,我们先来理解一下图像浏览器在移动设备上的重要性。一个良好的图像浏览器能够帮助用户轻松地查看、管理、分享和编辑他们的照片。Google作为全球领先的科技公司,其在...

    猫影视源代码JAVA开源 Andriod studio 源代码工程文件 有能力可自行二开

    【标题】"猫影视源代码JAVA开源 Andriod Studio 源代码工程文件 有能力可自行二开"指的是一个基于Java编程语言开发的Android应用程序——猫影视的源代码项目。这个开源项目允许开发者查看、学习甚至修改源代码,以...

    Google Android 应用开发揭秘 源代码

    "Google Android 应用开发揭秘 源代码"提供了深入理解Android应用构建过程的机会,让我们能够直接探索那些专业开发者是如何实现各种功能和交互的。这个压缩包包含了《Android应用开发揭秘》一书的源码,这本书可能是...

    安卓即时通讯工具源代码

    1. **用户身份验证**:用户注册和登录通常涉及到服务器端的数据存储和验证,源代码中可能会包含网络请求库(如OkHttp或Volley)的使用,以及JSON解析(如Gson或Jackson)来处理服务器返回的数据。 2. **消息传输**...

    google搜索源代码

    google搜索源代码

    《TensorFlow技术解析与实战》配套源代码

    《TensorFlow技术解析与实战》是一本专注于深度学习框架TensorFlow的专业书籍,旨在帮助读者深入...因此,对于想要深入学习和应用TensorFlow的开发者来说,《TensorFlow技术解析与实战》的配套源代码是一份宝贵的资源。

    google map api开发源代码

    这个源代码压缩包提供了一种实现Google Map API二次开发的实例,对于想要深入理解和应用这一技术的人来说非常有价值。 首先,我们要理解Google Map API的基本概念。它是一个JavaScript库,通过在网页中引入特定的...

    labview调用google地图源代码.zip源码Labview个人项目资料程序资源下载

    labview调用google地图源代码.zip源码Labview个人项目资料程序资源下载labview调用google地图源代码.zip源码Labview个人项目资料程序资源下载labview调用google地图源代码.zip源码Labview个人项目资料程序资源下载...

    google源代码

    google 源代码

    Android 4.2.2源代码

    《深入解析Android 4.2.2源代码》 Android 4.2.2是Google在2012年发布的一个重要版本,它在前代系统的基础上进行了诸多改进和优化,为开发者提供了更加稳定和高效的开发环境。源代码的开放性使得开发者能够深入理解...

    GPS定位并调用谷歌地图源代码

    本项目标题为"GPS定位并调用谷歌地图源代码",意味着它提供了使用GPS获取位置信息,并在谷歌地图上进行展示的编程实践。以下将详细介绍相关知识点。 1. GPS定位原理:全球定位系统(GPS)通过接收来自多个卫星的...

    Android经典项目开发实战_源代码

    13. **Material Design**:Google推出的Material Design设计语言在Android开发中广泛使用,源代码可能会展示如何遵循这一设计指南创建界面。 14. **第三方库集成**:许多Android开发者会使用如Butter Knife(注解...

Global site tag (gtag.js) - Google Analytics