SoftReference的介绍以及在Tapestry4中页面池的应用

软引用(Soft  Reference)的主要特点是具有较强的引用功能。只有当内存不够的时候才回收这类内存,因此在内存足够的时候,他们通常不被回收。另外,这些引用 对象还能保证在Java  抛出OutOfMemory异常之前,被设置为null。他可以用于实现一些常用资源的缓存,实现Cache的功能,保证最大限度的使用内存而不引起 OutOfMemory异常。

下面是软引用的实现代码:
 
 1 /**
 2 * 该类演示了Soft Reference的应用
 3 * 版权 本文版权属Java天下
 4 */

 5 package  cn.javatx;
 6
 7 import  java.lang.ref.SoftReference;
 8
 9 /**
10 * @author ajie
11 */

12
13 public   class  softReference  {
14
15    /**
16     * @param args
17     */

18    public static void main(String[] args) {
19        // TODO Auto-generated method stub
20        A a = new A();
21        
22        //使用a
23        a.test();
24
25        //使用完了a,将它设置为soft引用类型,并且释放强引用
26        SoftReference sr = new SoftReference(a);
27        a = null;
28       
29        //下次使用
30        if (sr.get() != null{
31            a = (A)sr.get();
32            a.test();
33        }
 else {
34            //GC由于低内存,已释放a,因此需要重新装载
35            a = new A();
36            a.test();
37            a = null;
38            sr = new SoftReference(a);
39        }

40    }

41
42}

43
44 class  A  {
45    public void test() {
46        System.out.println("Soft Reference test");
47    }

48}

49


        软引用技术的引进使Java应用可以更好的管理内存,稳定系统,防止系统内存溢出,避免系统崩溃。因此在处理一些占用内存大而且声明周期较长,但使用并不 频繁的对象时应尽量应用该技术。但事物总带有两面性的,有利也有弊,在 某些时候对软引用的使用会降低应用的运行效率与性能,例如:应用软引用的对象的初始 化过程较为耗时,或者对象的状态在程序的运行过程中发生了变化,都会给重新创建对象与初始化对象带来不同程度的麻烦,有些时候我们要权衡利弊择时应用。


Tapestry4.0.x版本的PagePool实现很简单,只是使用一个map容器作为缓存,高并发的情况下容易导致 OutOfMemoryException,下面是邮件列表中的相关内容,里边也提到了相关建议,估计会作为一个bug修改,在未修改之前,我会给出一个 简单实现。

PagePool doesnt remove idle pages, heap memory doens't get reallocated

> ----------------------------------------------------------------------
>
> Key: TAPESTRY-1151
> URL: http://issues.apache.org/jira/browse/TAPESTRY-1151
> Project: Tapestry
> Issue Type: Bug
> Components: Framework
> Affects Versions: 4.0
> Environment: java 1.4, apache tomcat 5.0 IBM websphere 5.0
> Reporter: lionel gomez
> Assigned To: Jesse Kuhnert
> Priority: Minor
>
> This may not qualify as a bug since its so easy to provide override using hivemind, but instead an improvement for future releases. Also provided an optional page pool implementation.
> Tapestry 4.0 PagePool implementation doesnt remove idle pages. When having hundred of pages with a lot of components and high user concurrency, tapestry generates many instances of each page. These instances are pooled and never unreferenced and never garbage collected. Our 1GB heap eventually fills up and reduces the memory available to other parts of the application. Eventually causes OutOfMemoryException.
> We ensured caching is enabled and config change made to use unique locale, but still, heap eventually fills up.
> With Hivemind its very easy to override the pagePool and provide different implementation. A page pool that uses softReferences is a good option.
> Acording to java api:
> All soft references to softly-reachable objects are guaranteed to have been cleared before the virtual machine throws an OutOfMemoryError.
> This prevents OEM due to heap filling up.
> New SoftPagePool only changes a couple of lines to use soft references.
> public synchronized Object get(Object key)
> {
> List pooled = (List) _pool.get(key);
> if (pooled == null || pooled.isEmpty())
> return null;
> _count--;
> SoftReference reference = (SoftReference) pooled.remove(0);
> //returns null if has been cleared by GC same as pool where empty
> return reference.get();
> }
> public synchronized void store(Object key, Object value)
> {
> List pooled = (List) _pool.get(key);
> if (pooled == null)
> {
> pooled = new LinkedList();
> _pool.put(key, pooled);
> }
> SoftReference reference = new SoftReference(value);
> pooled.add(reference);
> _count++;
> }
> Additionally the page pool implementation can use a clean idle pages mechanism using same design as Tapestry 3.0 ThreadJanitor or setting a timestamp when storing pages and a TimerTask and Timer wich receives events on registry shutdown. All this by using hivemind overriding features.

java类实现代码:

java 代码
  1. public class SoftReferenceObjectPool implements ObjectPool, ResetEventListener,   
  2.         ReportStatusListener {   
  3.     private String _serviceId;   
  4.   
  5.     private int _count = 0;   
  6.   
  7.     private Map _pool = new HashMap();   
  8.   
  9.     public synchronized Object get(Object key) {   
  10.         List pooled = (List) _pool.get(key);   
  11.         if (pooled == null || pooled.isEmpty())   
  12.             return null;   
  13.         _count--;   
  14.         SoftReference reference = (SoftReference) pooled.remove(0);   
  15.         // returns null if has been cleared by GC same as pool where empty   
  16.         return reference.get();   // 从软引用中取得
  17.     }   
  18.   
  19.     public synchronized void store(Object key, Object value) {   
  20.         List pooled = (List) _pool.get(key);   
  21.         if (pooled == null) {   
  22.             pooled = new LinkedList();   
  23.             _pool.put(key, pooled);   
  24.         }  
  25.         SoftReference reference = new SoftReference(value);   // 转为软引用储存
  26.         pooled.add(reference);   
  27.         _count++;   
  28.     }   
  29.   
  30.     public synchronized void resetEventDidOccur() {   
  31.         _pool.clear();   
  32.   
  33.         _count = 0;   
  34.     }   
  35.   
  36.     public synchronized void reportStatus(ReportStatusEvent event) {   
  37.         event.title(_serviceId);   
  38.   
  39.         event.property("total count", _count);   
  40.   
  41.         event.section("Count by Key");   
  42.   
  43.         Iterator i = _pool.entrySet().iterator();   
  44.   
  45.         while (i.hasNext()) {   
  46.             Map.Entry entry = (Map.Entry) i.next();   
  47.   
  48.             String key = entry.getKey().toString();   
  49.   
  50.             List pooled = (List) entry.getValue();   
  51.   
  52.             event.property(key, pooled.size());   
  53.         }   
  54.     }   
  55.   
  56.     public void setServiceId(String serviceId) {   
  57.         _serviceId = serviceId;   
  58.     }   
  59.   
  60. }  

 

查找了一下hivemind中用到ObjectPool的地方,共有三处,分别替换之。

xml 代码
  1. <implementation service-id="tapestry.page.PagePool">  
  2.      <invoke-factory>  
  3.       <construct class="org.edynasty.tapestry.pool.SoftReferenceObjectPool">  
  4.       <event-listener service-id="tapestry.ResetEventHub"/>  
  5.       <event-listener service-id="tapestry.describe.ReportStatusHub"/>  
  6.       </construct>  
  7.       </invoke-factory>  
  8.   </implementation>  
  9.   
  10. <implementation service-id="tapestry.GlobalObjectPool">  
  11.      <invoke-factory>  
  12.       <construct class="org.edynasty.tapestry.pool.SoftReferenceObjectPool">  
  13.       <event-listener service-id="tapestry.ResetEventHub"/>  
  14.       <event-listener service-id="tapestry.describe.ReportStatusHub"/>  
  15.       </construct>  
  16.       </invoke-factory>  
  17.   </implementation>  
  18.   
  19.   <implementation service-id="tapestry.request.EnginePool">  
  20.      <invoke-factory>  
  21.       <construct class="org.edynasty.tapestry.pool.SoftReferenceObjectPool">  
  22.       <event-listener service-id="tapestry.ResetEventHub"/>  
  23.       <event-listener service-id="tapestry.describe.ReportStatusHub"/>  
  24.       </construct>  
  25.       </invoke-factory>  
  26.   </implementation> 

 


 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值