博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入理解Ehcache系列(五)
阅读量:6241 次
发布时间:2019-06-22

本文共 5015 字,大约阅读时间需要 16 分钟。

hot3.png

        Ehcache中可以使用Cache来保存需要缓存的对像,但需要把对象封装在Element的实例里。

   往Cache中添加对像:  

CacheManager manager = CacheManager.newInstance("src/config/cache.xml");   manager.addCache("testCache");Cache cache = singletonManager.getCache("testCache");Element element = new Element("key", "value");      cache.put(element);

  

   相应源码:

       /**     * Put an element in the cache.     * 

     * Resets the access statistics on the element, which would be the case if it has previously been     * gotten from a cache, and is now being put back.     * 

     * Also notifies the CacheEventListener that:     * 
         * 
  • the element was put, but only if the Element was actually put.     * 
  • if the element exists in the cache, that an update has occurred, even if the element would be expired     * if it was requested     * 
     * 

     * Caches which use synchronous replication can throw RemoteCacheException here if the replication to the cluster fails.     * This exception should be caught in those circumstances.     *     * @param element A cache Element. If Serializable it can fully participate in replication and the DiskStore. If it is     *                null or the key is null, it is ignored as a NOOP.     * @throws IllegalStateException if the cache is not {@link Status#STATUS_ALIVE}     * @throws CacheException     */    public final void put(Element element) throws IllegalArgumentException, IllegalStateException,            CacheException {        put(element, false);    }

   Element UML类图:

 140749_rAab_1050156.png     

         构造一个Element对象很简单,Cache没有什么复杂的操作。但看似简单的put操作,它的实现是还有点复杂。

  Step 1:  开发者调用Cache的put方法。

cache.put(element);

   Step 2:  对应的源码

public final void put(Element element) throws IllegalArgumentException, IllegalStateException,            CacheException {        put(element, false);    }

 Step 3:  默认情况下doNotNotifyCacheReplicators的值是false.暂时先不讨论集群。

     private void putAll(Collection<Element> elements, boolean doNotNotifyCacheReplicators) throws IllegalArgumentException,

            IllegalStateException, CacheException {

        putAllInternal(elements, doNotNotifyCacheReplicators);

    }

Step 4:  具体实现细节。 可以大概看一下,今天我们主要分析一下 putObserver这个变量的作用。

private void putInternal(Element element, boolean doNotNotifyCacheReplicators, boolean useCacheWriter) {        putObserver.begin();        if (useCacheWriter) {            initialiseCacheWriterManager(true);        }        checkStatus();        if (disabled) {            putObserver.end(PutOutcome.IGNORED);            return;        }        if (element == null) {            if (doNotNotifyCacheReplicators) {                LOG.debug("Element from replicated put is null. This happens because the element is a SoftReference" +                        " and it has been collected. Increase heap memory on the JVM or set -Xms to be the same as " +                        "-Xmx to avoid this problem.");            }            putObserver.end(PutOutcome.IGNORED);            return;        }        if (element.getObjectKey() == null) {            putObserver.end(PutOutcome.IGNORED);            return;        }        element.resetAccessStatistics();        applyDefaultsToElementWithoutLifespanSet(element);        backOffIfDiskSpoolFull();        element.updateUpdateStatistics();        boolean elementExists = false;        if (useCacheWriter) {            boolean notifyListeners = true;            try {                elementExists = !compoundStore.putWithWriter(element, cacheWriterManager);            } catch (StoreUpdateException e) {                elementExists = e.isUpdate();                notifyListeners = configuration.getCacheWriterConfiguration().getNotifyListenersOnException();                RuntimeException cause = e.getCause();                if (cause instanceof CacheWriterManagerException) {                    throw ((CacheWriterManagerException)cause).getCause();                }                throw cause;            } finally {                if (notifyListeners) {                    notifyPutInternalListeners(element, doNotNotifyCacheReplicators, elementExists);                }            }        } else {            elementExists = !compoundStore.put(element);            notifyPutInternalListeners(element, doNotNotifyCacheReplicators, elementExists);        }

      

   putObserver,只看名字,第一反应就知道,这也许是一个观察者。Right! 

   private final OperationObserver
 putObserver = operation(PutOutcome.class).named("put").of(this).tag("cache").build();

 附上相关调用的UML类图,方便大家理解。

161715_ziqk_1050156.png

        Cache类依赖StatisticBuilder的operation()方法,通过StatisticsManager来创建GeneralOperationStatistic类的一个实例。此实例实现了OperationObserver接口的begin()和end()方法。

 putObserver.begin(); 

170949_zS67_1050156.png

 注:个人觉得这个地方的代码其实是运行不到的,因为它的addDerivedStatistic方法也没有被调用到。或者是我疏忽了哪个地方,还请知情人士贡献一下。get的被用到了,下节我会详细介绍。  

putObserver.end(elementExists ? PutOutcome.UPDATED : PutOutcome.ADDED);

对应的操作:

171009_nkcj_1050156.png

注: increment()是org.terracotta.statistics.jsr166e.LongAdder类下面基于CAS原理实现的一个线程安全的自增方法。感兴趣的朋友可以reference这个link:

 

     

       从我们的调查结果中可以看出,putObserver主要目的是统计put操作时ADDED,UPDATED,IGNORED的个数。 虽然结果很简单,但更多的是让我们知道了它的设计理念以及思想。虽然实现起来很复杂,但代码看起来还是那么的简洁。

         

        

 

 

转载于:https://my.oschina.net/zookeeper/blog/186004

你可能感兴趣的文章
Hash与Map
查看>>
sqlmap使用笔记
查看>>
U盾技术学习笔记
查看>>
云计算面临的安全挑战 访北大计算机学院院长陈钟
查看>>
一起谈.NET技术,C#中标准Dispose模式的实现
查看>>
艾伟:C#对游戏手柄的编程开发-API篇(2)
查看>>
关于defineProperty的一点理解
查看>>
如何创建只读域控制器RODC(Read-Only Domain Controller)
查看>>
python-字符串
查看>>
LabVIEW串口通信
查看>>
2017UGUI之slider
查看>>
python下载酷狗音乐源码
查看>>
MySQL学习----explain查看一条sql 的性能
查看>>
第零次作业
查看>>
Android + eclipse +ADT安装完全教程
查看>>
【批处理学习笔记】第七课:简单的批处理命令(6)
查看>>
leetcode 【 Subsets 】python 实现
查看>>
leetcode 【 Intersection of Two Linked Lists 】python 实现
查看>>
codeforces 767A Snacktower(模拟)
查看>>
用 Quartz 画聊天对话框背景实例
查看>>