缓存的简单实现方式

参考: 《Java 并发实践》 李大狗大神的大作和源码非常值得分析阅读

1.StringhashCode:数据缓存在类变量中

字符串类维护了一个常量池—每当使用String str="xxx"创建对象,都会首先检查字符串是否在常量池中—有的话直接返回池中对象的实例引用,否则则创建一个对象返回并将对象放进池中

没当调用 String.hashCode()方法时,字符串的hashCode便会缓存在String类变量中,下次查询是直接返回。

2.数据缓存在XXHashMap

HashMapConcurrentHashMap是最简单的缓存实现,必须使用缓存的项目初期可用XXHashMap实现。注意点有:

  1. 数据量不可太大,因为百万级别数据的扩容会耗费很长时间,可能造成后续数据积压。参考
  2. key获取value消耗时间太长的话,<K,V>V存放 FutrueTask<Value>
  3. k->v 的计算过程如果被取消或者中断,value存放的是无效的value, 此时需要移除无效的value,常用代码如下:
...
try{
    return feature.get();
}catch(Exception e){
    cache.remove(key);
}
...

综上,稍合理的缓存实现如下:

/**
 *计算接口
 */
public interface Computable<K,V>{
    V compute(A arg) throws InterruptedException;
}

/**
 *带有缓存实现的计算接口
 */
public class CachedComputer<K,V> implements Computable<K,V>{
    private final ComcurrentMap<K,Future<V>> cache = new ConcurrentHashMap<A,Future<V>>();

    private final Computable<K,V> c;

    public CachedComputer(Computable<K,V> c){
        this.c=c;
    }

    @Override
    public V compute(final K key) throws InterruptedException{
        while(true){
            Future<V> f=cache.get(key);
            if(f==null){
                Callable<V> eval=new Callable<V>(){
                    @Override
                    public V call() throws InterruptedException{
                        return c.compute(key);
                    }
                };
                FutureTask<V> ft=new FutureTask<V>(eval);
                f=cache.putIfAbsent(key,ft);
                if(f==null){
                    f=ft;
                    f.run();
                }
            }
            try{
                return f.get();
            }Cache(Exception e){
                cache.remove(key);
            }
        }
    }

}
3. 第二节的补充

第二节的实现仍然有几个问题亟ji2待解决:

  1. 缓存逾期问题—旧值逾期报废以为新值腾出空间;
  2. 缓存大小问题。

解决方法如下:

//逾期报废
value 包装成带有时间戳的对象(k,v,time),当put()或者get()时更新时间为System.currentTime();

启动线程检查逾期的value并移除,并且每次执行都sleep()一定的时间。

//缓存大小
使用LRU策略。

原文地址:https://www.cnblogs.com/dugk/p/9742315.html

时间: 2024-10-13 02:01:17

缓存的简单实现方式的相关文章

最简单的方式教你理解大小端字节序

学过编程的人都应该知道大小端字节序的概念,但是很多时候,总是把他们弄混,这是整理出来的一份很简单的方式理解字节序的文章,废话不多说,这里直接入正题. 什么是字节序? 字节序,简单来说,就是指的超过一个字节的数据类型在内存中存储的顺序 那么就很明显了,像char这样的类型,肯定不存在字节序的问题了. 字节序分为哪几类? 大端字节序: 高位字节数据存放在低地址处,低位数据存放在高地址处: 小段字节序: 高位字节数据存放在高地址处,低位数据存放在低地址处: 网络字节序: TCP/IP协议传输数据时,字

Nginx专题: upstream模块和缓存的简单使用

Nginx专题: upstream模块和缓存的简单使用 前言: 本文接着上篇Nginx专题: 从编译安装到URL重写来介绍Nginx的负载均衡模块使用方法, 本文的实验没有考虑大多数情况, 例如两个web服务器之间的数据同步等, 主要写Nginx如何作为负载均衡器使用并且缓存 实验拓扑 实验环境 主机 IP地址 功用 lb.anyisalin.com 172.16.1.2 负载均衡并缓存静态资源 web1.anyisalin.com 172.16.1.3 提供web服务 web2.anyisal

java最简单的方式实现httpget和httppost请求

java实现httpget和httppost请求的方式多种多样,个人总结了一种最简单的方式,仅仅需几行代码,就能够完美的实现. 此处须要用到两个jar包,httpclient-4.3.1.jar.httpcore-4.3.jar,各位能够到网上自己下载,或者到我的附件里下载,以下先贴上httpget请求的代码: String url = ""; HttpGet request = new HttpGet(url); try { HttpResponse response = HttpC

简单的方式实现javascript 小数取整

JS: function truncateNumber(n){ return n|0; } 测试: console.log(truncateNumber(12.345)); 浏览器打印出12 简单的方式实现javascript 小数取整

使用NSURLProtocol实现UIWebView的离线缓存的简单实现

文章介绍了使用NSURLProtocol实现UIWebView的离线缓存的简单实现,你可以在github上下载这个demo的代码. 无论是"MKNetworkKit"还是"AFCache"实现的缓存都过于复杂,而他想要的是一个简单机制: 1.你使用了UIWebView指向来显示一个有图像嵌入的网站. 2.当你的设备online时,你有正常的缓存算法. 3.当你的设备offline时,你可以显示页面的最后一个版本. 这个demo里做了一个很简单的测试:将cnn.com

PVS让存储颤抖,系列博文之四:PVS的写缓存新技术之XenApp方式实测篇

XenApp运行环境 XenApp 6.5运行在Windows 2008 R2上 和运行VDI的测试类似,XenApp的测试方式如出一辙.LoginVSI还是设置为中等负荷,使用同样的用户帐号设置,也是同样的用户配置文件设置.不过用户配置文件我们使用的是优化了的配置文件管理.另外,XenApp虚拟机一般来说数量较少而内存较大,所以我们侧视了几种Cache in RAM with Hard Disk Overflow的大小,包括1GB.3GB以及12GB的内存,测试结果在下面. XenApp 6.

JSONP的简单实现方式(原来不是非得用jQuery!!)

如题,在做跨域的时候时常要用到JSONP.以前用到JSONP去网站找到的示例都是jQuery实现的. 直到最近在做一个网页的时候,因为要求网页加载很快.不得不考虑去掉jQuery. 但是我找到如下的简单实现方式. <script> function jsonpCallback(result) { alert(result); } </script> <script src="http://XX.XX.XX?callback=jsonpCallback"&g

辛星和您用更简单的方式去实现PHP中的验证码

说实话,提到验证码我想大家都不会陌生,确实,验证码还是挺常见的,现在搜索一下PHP的验证码类简直是海量的数据,那我们今天就来实现一个自己的验证码把,不过它比较简单,这也是我说的用更简单的方式去实现一个验证码. 总的来说分成两步,第一步就是先实现一个验证码,第二步就是通过这个验证码来进行验证,我们先看一下如何去实现这个验证码,当然这里需要用到gd库的知识,请看下面的代码示例: <?php //首先要开启session session_start(); //说明这是一张图片 header("C

Openfire3.8.2在eclipse中Debug方式启动最简单的方式

一.前言 最近打算研究一下Openfire,于是打算最好能够以Debug方式启动Openfire的Server,到网上一搜,还果真早到官网的一篇文章来: http://community.igniterealtime.org/docs/DOC-1020 网上很多朋友按照这个教程去搭建,有的说文章有瑕疵的地方,姑且不说瑕疵,就这很长的步骤令人厌恶.本来我想按照这个教程去做,但是,单使用 Eclpse SVN下载令人崩溃,一直显示进度为0%,后来换了TortoiseSVN好一些,下载了两次,每次都花