常用优化二、缓存

缓存(cache)

缓存也是为了提高系统性能而开辟的内存空间。缓存主要作用是暂存数据处理结果,并提供下次访问使用。在很多场合,数据的处理和数据的获取会非常费时,当对这个数据的请求量很大时,频繁的数据处理会耗尽CPU资源,缓存的作用就是将这些来之不易的数据处理结果暂存起来,当有其他线程或者客户端需要查询相同的数据资源时,可以省略对这些数据的处理流程,而直接从缓存中获取处理结构,并立即返回处理组件,以此提高系统的响应时间。

缓存的使用非常普遍,比如目前流行的几种浏览器都会在本地缓存远程的页面,从而减少远程HTTP的访问次数,加快网页的加载速度。又比如在服务端的系统开发中,设计人员可以为一些核心的API加上缓存,从而提高系统的整体性能。
最为简单的缓存可以直接使用HashMap来实现,当然这样做会遇到很多问题,何时应该清理无效的数据,如何防止缓存数据过多而导致内存溢出等。一个稍好的替代方案是直接使用WeakHashMap,它使用弱引用维护一张哈希表,从而避免了潜在的内存溢出问题,但是作为专业的缓存,它的功能也略有不足。
幸运的是,目前有很多基于java的缓存框架,比如EHCache、OSCache和JBossCache等。
EHCache出自Hibernate,是Hibernate框架默认的数据解决方案。
OSCache是由OpenSymphony,它可以用于缓存任何对象,甚至是缓存部分JSP页面,或者HTTP请求。
JBossCache是由JBoss开发,可用于JBoss集群间,数据共享的缓存框架。
以EHCache缓存为例,介绍一下缓存的使用方法:

diskStore
diskStore元素:制定一个路径,当EHCache把数据写到硬盘上的时候,
会把数据写到该目录下。user.home - 用户主目录;user.dir - 用户当前工作目录;
java.io.tmpdir - 默认临时文件路径。

defaultCache
设定缓存的默认数据过期策略。

cache
设定具体的命名缓存的数据过期策略。

name
缓存名称。通常为缓存对象的类名;

maxElementsInMemory
设置基于内存的缓存可存放对象的最大数目;

maxElementOnDisk
设置基于硬盘的缓存可存放对象的最大数目;

eternal
如果为true,表示对象永远不会过期,此时会忽略tiemToldleSeconds和timeToLiveSeconds属性
默认为false。

timeToldleSeconds
设置允许对象处于空闲状态的最长时间,以秒为单位。
当对象最近一次被访问后,如果处于空闲状态的时间超过了
timeToldleSeconds属性值,这个对象就会过期。
当对象过期,EHCache将把它从缓存中清空。只有当eternal属性为false.
该属性才有效。如果该属性的值为0,那么就表示该对象可以无限期地存于缓存中。
即缓存被创建后,最后一次访问时间到缓存失效之时,两者之间的间隔,单位为秒(s)

timeToLiveSeconds
必须大于timeToldleSeconds属性,才有意义;
当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,
这个对象就会过期,EHCache将把它从缓存中清除;
即缓存自创建日期起能够存活的最长时间,单位为秒(s)

overflowToDisk
如果为true,表示当基于内存的缓存中的对象数目达到了maxElementsInMemory界限后
会把溢出的对象写到基于硬盘的缓存中。
注意,如果缓存的对象要写入到硬盘中的话,则该对象必须实现了Serializable接口才行(也就是序列化);

memoryStoreEvictionPolicy
缓存对象清除策略。
有三种:
FIFO:first in first out
先进先出。
LFU:Less Frequently Used
一直以来最少被使用策略,缓存元素有一个hit属性,hit(命中)值最小的将会被清除出缓存。
LRU:least Recenly used
最近最少被使用,缓存的元素有一个时间戳,当缓存的容量满了,
而又需要腾出地方来缓存新的元素的时候,
那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。

diskSpoolBufferSizeMB
写入磁盘的缓冲区大小。
由于diskSpoolBufferSizeMB在内部实际是以字节为单位,
所以最大值是Integer的最大值即2047.99…M,反正不到2G。
所以如果配置的超过2G,将会导致diskSpoolBufferSizeMB为负数,
在put时ehcache误以为磁盘缓存队列已满,每次都执行都会阻塞。

maxElementsOnDisk
在DiskStore(磁盘存储)中的最大对象数量,如为0,则没有限制

diskPersistent
是否disk store在虚拟机启动时持久化。默认为false

diskExpiryThreadIntervalSeconds
Ehcache后台线程专门做Ellment失效监测以及清除工作。
此值不宜设置过低,否则会导致清理线程占用大量CPU资源。
默认值是120秒。

clearOnFlush
当调用flush()是否清除缓存,默认是。

maxEntriesLocalHeap
堆内存中最大缓存对象数,0没有限制


ehcache-setting.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
 	<!-- 指定一个文件目录,当EhCache把数据写到硬盘上时,将把数据写到这个文件目录下 -->
	<diskStore path="D://cui" />
	<!-- 设定缓存的默认数据过期策略 -->
	<defaultCache maxElementsInMemory="10000"
            eternal="false"    
            timeToIdleSeconds="120"    
            timeToLiveSeconds="120"    
            overflowToDisk="true"    
            diskPersistent="false"    
            diskExpiryThreadIntervalSeconds="120" />
      <cache name="cache1" maxElementsInMemory="10000"
            eternal="false"    
            timeToIdleSeconds="120"    
            timeToLiveSeconds="120"    
            overflowToDisk="true"    
            diskPersistent="false"    
            diskExpiryThreadIntervalSeconds="120"/>
      <cache name="cache2" maxElementsInMemory="10000"
            eternal="false"    
            timeToIdleSeconds="120"    
            timeToLiveSeconds="120"    
            overflowToDisk="true"    
            diskPersistent="false"    
            diskExpiryThreadIntervalSeconds="120"/>
</ehcache> 

EHCache使用简单,可以向使用HashMap一样使用它,为了方便使用,我们将EHCahce进行封装。

EHCache工具类:

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class EHCacheUtil {
	//首先初始化EHCache
	private static final String path="ehcache-setting.xml";
	private URL url;
	private CacheManager manager;
	private static EHCacheUtil ehCache;
	
	private EHCacheUtil(String path) {
		url=getClass().getResource(path);
		manager=CacheManager.create(url);
	}
	public static EHCacheUtil getInstance() {
		if(ehCache==null) {
			ehCache=new EHCacheUtil(path);
		}
		return ehCache;
	}
	public void put(String cacheName,String key,Object value) {
		Cache cache=manager.getCache(cacheName);
		Element element=new Element(key, value);
		cache.put(element);
	}
	public Object get(String cacheName,String key) {
		Cache cache=manager.getCache(cacheName);
		Element element=cache.get(key);
		return element==null?null:element.getObjectValue();
	}
	public Cache get(String cacheName) {
		return manager.getCache(cacheName);
	}

    public void remove(String cacheName, String key) {  
        Cache cache = manager.getCache(cacheName);  
        cache.remove(key);  
    } 
}

使用:
public class Demo {
	public static void main(String[] args) throws Exception {
		EHCacheUtil ehUtil=EHCacheUtil.getInstance();
		ehUtil.put("cache1", "name", "cuixiansheng");
		String name=(String) ehUtil.get("cache1", "name");
		System.out.print(name);
	}
}
结果:
cuixiansheng

maven依赖:
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-nop -->
	<dependency>
	    <groupId>org.slf4j</groupId>
	    <artifactId>slf4j-nop</artifactId>
	    <version>1.7.25</version>
	    <scope>test</scope>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值