`
qq4628241
  • 浏览: 62638 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Java缓存中弱引用应用

 
阅读更多
问题描述:
SEOURL 跳转地址的cache。利用map key(SeoCacheKey) value(url)的方式缓存,以每2小时策略和Entry<15000条策略,以及Memery<?策略更新缓存。由于key的设计过于粗狂,导致
key在缓存中占用太多内存,且key中的核心property生命周期过长,导致失真。
解决方案:
利用WeakReference弱引用,管理最初的核心property,使之成为一个真实的,不会导致memery膨胀的object。
代码如下,无需关注其他内容,最重要的是弱引用的实现和使用
public class SeoCacheKey {
	
	private static ReferenceQueue<RepositoryItem> PREFERENCEQUEUE =  new ReferenceQueue<RepositoryItem>();
	
    WeakReference<RepositoryItem> mRepositoryItemReference;
    
    Repository	mRepository;

    
    public SeoCacheKey(UrlTemplate pUrlTemplate, RepositoryItem pRepositoryItem, String pContextRoot) {
        this.mRepository = pRepositoryItem.getRepository();
		//弱引用管理此核心property对象
        this.mRepositoryItemReference = new WeakReference<RepositoryItem>(pRepositoryItem, PREFERENCEQUEUE);
    }
    
	//由于使用时存在多线程,同步此方法,确保换取后对象在生命周期内的唯一性
	public synchronized RepositoryItem getRepositoryItem(){
		
		RepositoryItem item = this.mRepositoryItemReference.get();
		if(item == null){
			if (StringUtil.empty(mItemID)) {
				throw (new IllegalArgumentException("The parameter \"mItemID\" can not be empty."));
			}
			if (StringUtil.empty(mItemDescriptorName)) {
				throw (new IllegalArgumentException("The parameter \"mItemDescriptorName\" can not be empty."));
			}
			try {
				item = mRepository.getItem(mItemID, mItemDescriptorName);
			} catch (RepositoryException e) {
				throw (new CustomRepositoryException("Can not get repository item whose id is " + mItemID + " and descriptor name is "
						+ mItemDescriptorName + ".", e));
			}
		}
		return item;
	}
}

关于java的强引用,软引用,弱引用,虚引用请google一把
如在工作中遇到需要做缓存的地儿,请不要忘记java中除了强引用(导致OutOfMemeryException)外,还有可爱的软引用,弱引用,以及可以监视对象被回收的虚引用。

对这个知识点的扩展之原子引用以确保原子性
public class SeoCacheKey {
	//原子引用
	AtomicReference<WeakReference<RepositoryItem>> mAtomicReference;
	
    WeakReference<RepositoryItem> mRepositoryItemReference;
    
    UrlTemplate urlTemplate;
    
    Repository	mRepository;
    
    String mRepositoryName;
    
    String mItemDescriptorName;
    
    String mItemID;

    String contextRoot;
    
    public SeoCacheKey(UrlTemplate pUrlTemplate, RepositoryItem pRepositoryItem, String pContextRoot) {
    	
    	this.urlTemplate = pUrlTemplate;
        this.mRepository = pRepositoryItem.getRepository();
        this.mRepositoryName = pRepositoryItem.getRepository().getRepositoryName();
        try {
			this.mItemDescriptorName = pRepositoryItem.getItemDescriptor().getItemDescriptorName();
		} catch (RepositoryException e) {
			throw new IllegalArgumentException("Get item descriptor name error!",e);
		}
        this.mItemID = pRepositoryItem.getRepositoryId();
        this.contextRoot = pContextRoot;
        WeakReference<RepositoryItem> repositoryItemReference = generateWeakReference(pRepositoryItem);
        this.mAtomicReference = new AtomicReference<WeakReference<RepositoryItem>>(repositoryItemReference);
    }
    
	public RepositoryItem getRepositoryItem() {
		RepositoryItem item = this.mAtomicReference.get().get();
		if (item != null) {
			return item;
		}
		if (StringUtil.empty(mItemID)) {
			throw (new IllegalArgumentException(
					"The parameter \"mItemID\" can not be empty."));
		}
		if (StringUtil.empty(mItemDescriptorName)) {
			throw (new IllegalArgumentException(
					"The parameter \"mItemDescriptorName\" can not be empty."));
		}
		try {
			item = mRepository.getItem(mItemID, mItemDescriptorName);
			WeakReference<RepositoryItem> repositoryItemReference = generateWeakReference(item);
			//确保了对象的原子性,使得其他线程在调用的这个类的时候,不会出现doublechecking的尴尬
			//关于doublechecking,请google。或参看http://spice.iteye.com/blog/1117370
			this.mAtomicReference.getAndSet(repositoryItemReference);
			return item;
		} catch (RepositoryException e) {
			throw (new CustomRepositoryException(
					"Can not get repository item whose id is " + mItemID
							+ " and descriptor name is " + mItemDescriptorName
							+ ".", e));
		}
	}

	private WeakReference<RepositoryItem> generateWeakReference(
			RepositoryItem item) {
		ReferenceQueue<RepositoryItem> referenceQueue = new ReferenceQueue<RepositoryItem>();
		WeakReference<RepositoryItem> repositoryItemReference = new WeakReference<RepositoryItem>(
				item, referenceQueue);
		return repositoryItemReference;
	}
}

分享到:
评论

相关推荐

    java弱引用

    弱引用的应用场景有很多,例如,在缓存机制中,我们可以使用弱引用来缓存对象,以便在内存紧张时释放这些对象。在图片处理中,我们可以使用弱引用来缓存图片,以便在内存紧张时释放这些图片。 弱引用是一种非常有用...

    十分钟理解Java中的弱引用编程开发技术共3页.pdf.z

    Java中的弱引用编程开发技术是Java内存管理的一个重要概念,对于优化内存使用和防止内存泄漏具有关键作用。本文将深入探讨这一主题,帮助你在这十分钟内建立起对弱引用的理解。 首先,我们需要知道Java的内存区域...

    Java中的软引用弱引用和虚引用.docx

    ### Java中的软引用、弱引用和虚引用详解 #### 一、引言 在Java开发过程中,特别是Android应用开发中,经常会遇到一个普遍的问题——内存溢出(OutOfMemory Error,简称OOM)。这个问题往往与如何有效地管理内存...

    java cache 简单应用

    在本文中,我们将深入探讨Java缓存的简单应用,并结合给出的资源——“JAVA的缓存应用.ppt”来进行讨论。 首先,让我们了解什么是缓存。缓存是计算机系统中用于临时存储数据的快速访问区域,目的是减少从主存储器或...

    java之反射优化(缓存思路)源码

    2. **软引用**:使用Java的`SoftReference`可以创建一个弱化的缓存,这样在内存紧张时,JVM会自动回收这些不再使用的反射对象,以释放内存。 ```java public class ReflectionUtil { private static Map, ...

    websphere缓存java调用以及jar包

    标题中的“websphere缓存java调用以及jar包”指的是在IBM WebSphere Application Server (WAS) 中使用Java编程方式来管理和操作缓存系统。WebSphere应用服务器提供了一种高效的方式来存储和检索频繁访问的数据,以...

    Java中的强软弱虚引用

    综上所述,Java中的四种引用类型按照引用强度由高到低依次是强引用、软引用、弱引用和虚引用。每种引用都有其适用场景: - **强引用**:用于保持对象的生命周期,确保对象不被垃圾回收。 - **软引用**:用于实现内存...

    Java缓存讨论.pdf

    Ehcache支持内存和磁盘缓存,提供对象过期策略,并且可以很容易地集成到各种Java应用中。 Java Caching System (JCS)是Apache Turbine的一个子项目,提供复合缓存功能,对象可以被缓存到内存和硬盘,并支持对象过期...

    Android中的软引用和弱引用

    在这个过程中,软引用(Soft Reference)和弱引用(Weak Reference)是两种非常重要的工具,它们可以帮助我们避免内存泄漏,提高应用的内存效率。下面我们将深入探讨这两种引用类型及其在Android中的应用。 首先,...

    Java的四种引用

    弱引用主要用于实现较弱的引用关系,如缓存中的元素。 **示例代码**: ```java String str = new String("hello"); ReferenceQueue&lt;String&gt; queue = new ReferenceQueue(); WeakReference&lt;String&gt; weakRef = new ...

    java 常见的四种引用

    在Java中,为了更好地管理对象的生命周期,从JDK 1.2开始引入了四种不同级别的引用类型:强引用、软引用、弱引用和虚引用。每种引用类型都有其特定的应用场景,通过灵活运用这些引用类型,开发者可以在内存管理和...

    android安卓图片的三级缓存DEMO 三层缓存示例下载 强引用 软引用

    这里的“软引用”是指Java中的软引用,它是一种弱化的引用,即使有软引用指向对象,只要发生垃圾回收并且内存不足,软引用的对象仍然会被回收。在磁盘缓存中,软引用可以防止图片在内存不足时立即被清理,但又允许在...

    详解 JAVA 弱引用

    因此,在获取弱引用对象的代码中,一定要判断是否为null,以免出现NullPointerException异常导致应用崩溃。 弱引用对象的生命周期可以通过WeakReferenceTest类来了解。该类中,我们创建了一个弱引用对象,并将其...

    基于java的java缓存工具 SimpleCache.zip

    Java 缓存技术在开发高效率、高性能的应用程序时起着至关重要的作用。SimpleCache 是一个基于 Java 的轻量级缓存工具,旨在提供简单易用的缓存解决方案。在这个 SimpleCache.zip 压缩包中,包含的是 SimpleCache 库...

    深入理解Java中的弱引用

    Java中的弱引用是一种特殊的引用类型,它允许程序员创建对对象的引用,但这些引用不会阻止对象被垃圾收集器回收。这种引用的引入主要是为了解决内存管理和缓存策略中的问题,尤其是在防止内存泄漏方面。 首先,我们...

    基于Java的实例源码-Java缓存工具 SimpleCache.zip

    【Java缓存工具 SimpleCache】是一个实用的Java编程示例,它展示了如何在应用程序中实现一个简单的缓存机制。在软件开发中,缓存是一种优化技术,用于存储频繁访问的数据,以便快速检索,减少对主数据库或其他计算...

    统计缓存(java对象所占的内存)大小

    当缓存大小成为问题时,可以通过调整缓存策略(如使用弱引用、软引用或计算对象的引用强度)来减少内存占用。同时,及时释放不再使用的对象,防止内存泄漏,也是提升系统稳定性和效率的重要手段。 总的来说,理解...

    拓胜技术专家教你如何深入理解Java四种引用类型

    Java中的四种引用类型是Java内存管理的重要组成部分,它们分别是强引用(StrongReference)、软引用(SoftReference)、弱引用(WeakReference)和虚引用(PhantomReference)。每种引用类型具有不同的特点和用途,...

    基于软引用实现的缓存,当内存不够使会自动释放缓存内容,以避免OOM

    本篇文章将深入探讨软引用在缓存中的应用以及其工作原理。 软引用是Java中的一个特殊引用类型,它表示一个弱化的引用,介于强引用和弱引用之间。强引用是默认的引用类型,只要对象被强引用指向,就不会被垃圾收集器...

Global site tag (gtag.js) - Google Analytics