All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.holmos.cache.element.Element Maven / Gradle / Ivy

package com.holmos.cache.element;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;

import com.holmos.cache.element.listener.ElementAccessListener;
import com.holmos.cache.size.layout.sizegetter.ReflectSizeGetter;
import com.holmos.cache.size.layout.sizegetter.SizeGetter;
import com.holmos.cache.size.layout.sizegetter.SizeGetterFactory;

/**
 * 缓存的元素类型,包含key,value和此元素的属性信息
 * 
 * @author: 吴银龙([email protected])
 * @version: 2013-3-7 下午12:48:29 
 */

public class Element implements Serializable,Cloneable,ElementAccessListener{

	private static final long serialVersionUID = -1032104732342127102L;
	
	private static ReflectSizeGetter sizeGetter;
	
	static{
		ArrayList getters=new ArrayList();
		getters.add(SizeGetterFactory.ARRAY_SIZE_GETTER);
		getters.add(SizeGetterFactory.OBJECT_SIZE_GETTER);
		sizeGetter = new ReflectSizeGetter(getters);
	}
	/**hitCount字段的原子更新器,因为hitCount是要被并发增加的,但只要保证最终正确就行*/
	private static final AtomicLongFieldUpdater HITCOUNT_UPDATER = AtomicLongFieldUpdater.newUpdater(Element.class, "hitCount");
	
	/**缓存元素访问监听器列表*/
	private ArrayList elementAccessListeners;
	
	/** the key */
	private Object key;
	
	/**the value */
    private Object value;

    /**采用乐观锁来控制读写的并发,version为当前元素的版本号*/
    private volatile long version;

    /**缓存元素在缓存中的命中率,get的时候,如果该元素在缓存中,则get一次此值+1*/
    private volatile long hitCount;

    /**此元素的现有可生存时间,一旦为0,则为失效元素(ms) */
    private volatile int timeToLive = Integer.MIN_VALUE;

    /**此元素剩余的闲置时间,如果时间一旦为0,则此为失效元素(ms) */
    private volatile int timeToIdle = Integer.MIN_VALUE;

    /**此元素的创建时间(ms),在replace操作的时候此时间也会发生更新*/
    private volatile long creationTime;

    /**元素的最近一次访问时间(ms)*/
    private volatile long lastAccessTime;

    /**元素发生更新操作的时候,put操作和replace操作,此属性更新为操作完成时间*/
    private volatile long lastUpdateTime;

    /**元素占用存储空间大小*/
    private int size;
    
    /**此值为真,那么不能进行写操作*/
    private volatile boolean writeLocked;
    
    /**此值为真,那么不能进行读操作*/
    private volatile boolean readLocked;
    
    
    /**
     * 以对象的形式返回value的值
     * 
     * 
  • 这个是用受JVM管理的内存的getValue的方法,不进行序列化处理,直接返回原生的缓存对象
  • * * @return 缓存元素对象 * */ public Object getValue(){ return value; } /** * 以对象形式返回索引key * *
  • 这个是用受JVM管理的内存的getKey的方法,不进行序列化处理,直接返回原生的缓存对象
  • * * @return 缓存元素的key属性 * */ public Object getKey(){ return key; } /** * 获取缓存元素占用内存大小,JVM内部缓存的占用空间大小,而非序列化之后的大小 * * @return 缓存元素占用空间大小 * */ public int getSize(){ if(0 == size) size=sizeGetter.getDataSize(value); return size; } /** * 判断该缓存元素是否和value是同一个缓存元素,判断的方法很简单,只要他们的key一致就判定他们是同一个元素,因为同一个缓存里面不可能存在两个key一致的情况 * *
  • 如果value == null 则返回false
  • *
  • 如果value 不是{@link Element}类型,则返回false
  • *
  • 如果元素自己和value的key有一个为null为错误情况,直接返回false
  • *
  • 如果元素自己的key和value的key不一致,返回false
  • * * @return true 两个缓存元素相同
    false 两个缓存元素不同 * */ @Override public boolean equals(Object value){ if( null== value ||!(value instanceof Element)) return false; Element element = (Element)value; if(null == key || element.getKey() == null) return false; if( key.equals(element.getKey())) return true; return false; } /** * 获取缓存元素的创建时间点(ms) * *
  • the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC.
  • * * @return 缓存元素的创建时间点(ms) * */ public long getCreationTime(){ return creationTime; } /** * 设置缓存元素的生存时间(单位:ms) * *
  • 0代表生存时间无限大
  • * * @param timeToLiveMilliseconds * */ public void setTimeToLive(int timeToLiveMilliseconds){ if(timeToLiveMilliseconds < 0 ) throw new IllegalArgumentException("缓存元素的生存时间不能设置为负数!"); timeToLive = timeToLiveMilliseconds; } /** * 获得缓存元素的最大生存时间 * * @return 缓存元素的最大生存时间 * */ public int getTimeToLive(){ return timeToLive; } /** * 设置缓存元素的最大空闲时间,即元素在最后一次访问或者创建到元素过期之间的最大时间(单位:ms) * *
  • 0代表永不过期
  • * * @param timeToIdleMilliseconds * */ public void setTimeToIdle(int timeToIdleMilliseconds){ if(timeToIdleMilliseconds < 0) throw new IllegalArgumentException("缓存元素的空闲时间不能设置为负数!"); timeToIdle = timeToIdleMilliseconds; } /** * 获得缓存元素的最大空闲时间 * * @return 缓存元素的最大空闲时间 * */ public int getTimeToIdle(){ return timeToIdle; } /** * 设置该缓存元素的版本号,由于该操作很频繁,在开发的时候注意版本号不能是负数,也尽量不要小于之前的版本号 * * @param version 待设置的版本号 * */ public void setVersion(long version){ this.version=version; } /** * 获取该元素当前的版本号 * * @return 该元素当前的版本号 * */ public long getVersion(){ return version; } /** * 获取最近的更新时间,如果还没有发生更新,则返回创建时间 * * @return 最近的更新时间 * */ public long getLastUpdateTime(){ if( 0 == lastUpdateTime ) return creationTime; return lastUpdateTime; } /** * 获取最近的访问时间,读取和更新的时候都会更新最近访问时间 * * @return 最近的访问时间 * */ public long getLastAccessTime(){ return lastAccessTime; } /** * 获取该缓存数据的命中次数 * * @return 缓存数据的命中次数 * */ public long getHitCount(){ return hitCount; } /** * 重置访问状态:置hitCount = 0,lastAccessTime = 当前时间,发生在put操作之后 * * * */ public void resetAccessStatistics(){ HITCOUNT_UPDATER.set(this, 0); lastAccessTime = System.currentTimeMillis(); lastUpdateTime = lastAccessTime; } /** * 更新访问状态:hitCount++,lastAccessTime = 当前时间,发生在get操作之后 * * */ public void updateAccessStatistics(){ HITCOUNT_UPDATER.incrementAndGet(this); lastAccessTime = System.currentTimeMillis(); } /** * 一旦元素的值发生改变,将会更新元素的 更新信息 * * 发生在update之后 * */ public void updateModifyStatistics(){ updateAccessStatistics(); lastUpdateTime = System.currentTimeMillis(); } /** * 获得缓存元素的描述信息 * * @return 元素的描述信息 * */ @Override public String toString(){ StringBuilder elementDescribe = new StringBuilder(); elementDescribe.append("[ key = ").append(key) .append(", value=").append(value) .append(", version=").append(version) .append(", hitCount=").append(hitCount) .append(", CreationTime = ").append(this.getCreationTime()) .append(", LastAccessTime = ").append(this.getLastAccessTime()) .append(" ]"); return elementDescribe.toString(); } /** * 查看缓存元素是否过期 * *
  • 首先校验缓存元素是否超过了生存时间,也就是说看看now-creationtime &rt timeToLive
  • *
  • 在没有超过生存时间的时候,看缓存元素的空闲时间是否过了空闲期限
  • * * @return true 缓存元素已过期
    false 缓存元素未过期 * */ public boolean isExpired(){ long expireTime = getExpireTime(); return expireTime < System.currentTimeMillis(); } /** * 获取缓存元素的过期时间,从生存时间和空闲时间双方面去考虑 * * @return 缓存元素的过期时间点 */ private long getExpireTime() { long liveExpireTime = creationTime+timeToLive; long idleExpireTime = Math.max(lastAccessTime, creationTime)+timeToIdle; return Math.min(liveExpireTime, idleExpireTime); } public boolean isWriteLocked() { return writeLocked; } public boolean isReadLocked() { return readLocked; } public synchronized boolean lockWrite(){ boolean oriWriteLock = this.writeLocked; this.writeLocked = true; return oriWriteLock; } public synchronized void releaseWrite(){ this.writeLocked = false; } public synchronized boolean lockRead(){ boolean oriReadLock = this.readLocked; this.readLocked = true; return oriReadLock; } public synchronized void releaseRread(){ this.readLocked = false; } public ArrayList getElementAccessListeners() { return elementAccessListeners; } public void registerElementAccessListener(ElementAccessListener elementAccessListener) { this.elementAccessListeners.add(elementAccessListener); } public void removeElementAccessListener(ElementAccessListener elementAccessListener){ this.elementAccessListeners.remove(elementAccessListener); } public void clearElementAccessListeners(){ this.elementAccessListeners.clear(); } @Override public void beforeGet() { for(ElementAccessListener listener:elementAccessListeners){ listener.beforeGet(); } } @Override public void afterGet() { for(ElementAccessListener listener:elementAccessListeners){ listener.afterGet(); } } @Override public void beforeInsert() { for(ElementAccessListener listener:elementAccessListeners){ listener.beforeInsert(); } } @Override public void afterInsert() { for(ElementAccessListener listener:elementAccessListeners){ listener.afterInsert(); } } @Override public void beforeUpdate() { for(ElementAccessListener listener:elementAccessListeners){ listener.beforeUpdate(); } } @Override public void afterUpdate() { for(ElementAccessListener listener:elementAccessListeners){ listener.afterUpdate(); } } @Override public void beforeDelete() { for(ElementAccessListener listener:elementAccessListeners){ listener.beforeDelete(); } } @Override public void afterDelete() { for(ElementAccessListener listener:elementAccessListeners){ listener.afterDelete(); } } }




    © 2015 - 2024 Weber Informatics LLC | Privacy Policy