文档章节

深入理解Ehcache系列(四)

ZooKeeper
 ZooKeeper
发布于 2013/12/18 18:11
字数 886
阅读 1394
收藏 35
点赞 0
评论 2

      在系列三中我们介绍了可以通过配置文件或者参数传递来配置Ehcache的系统参数。但是如果我们想动态的去调整这些参数应该怎么办呢?

      这是完全可行的,Cache提供了相应的方法。


Cache cache = manager.getCache("sampleCache");
CacheConfiguration config = cache.getCacheConfiguration();
config
.setTimeToIdleSeconds(60);
config
.setTimeToLiveSeconds(120);
config
.setmaxEntriesLocalHeap(10000);
config
.setmaxEntriesLocalDisk(1000000);


/**
     * @param propertyName
     * @param oldValue
     * @param newValue
     */
    public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
      PropertyChangeSupport pcs;
      synchronized (this) {
        pcs = propertyChangeSupport;
      }
      if (pcs != null && (oldValue != null || newValue != null)) {
        pcs.firePropertyChange(propertyName, oldValue, newValue);
      }
    }



       先让我们来回忆一下PropertyChangeSupport的具体用法。


PropertyChangeSupport类的官方文档解释:
     

This is a utility class that can be used by beans that support bound properties.  You can use an instance of this class as a member field of your bean and delegate various work to it.



     关联属性,也称绑定属性。当绑定属性值发生变化时,通知所有相关的监听器。为了实现属性绑定,必须实现两个机制。


  1. 只要属性的值发生变化,该bean发送一个PropertyChange事件给所有已注册的监听器。该变化可以发生在调用set方法时,或者程序的用户做出某种动作时。

  2. 为了使感兴趣的监听器能够进行注册,bean必须实现以下两个方法:



void addPropertyChangeListener(PropertyChangeListener listener);
void removePropertyChangeListener(PropertyChangeListener listener);

    通过java.bean包下的PropertyChangeSupport类来管理监听器。要使用这个类,bean必须有一个此类的数据域。



private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);


    /**
     * @param listener
     */
    public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
      if (listener != null && propertyChangeSupport != null) {
        propertyChangeSupport.removePropertyChangeListener(listener);
        propertyChangeSupport.addPropertyChangeListener(listener);
      }
    }


    /**
     * @param listener
     */
    public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
      if (listener != null && propertyChangeSupport != null) {
        propertyChangeSupport.removePropertyChangeListener(listener);
      }
    }



    bean的属性发生变化时,使用PropertyChangeSupport对象的firePropertyChange方法,它会将一个事件发送给所有已经注册的监听器。该方法有三个参数:属性的名字、旧的值以及新的值。属性的值必须是对象,如果是简单数据类型,则必须进行包装。

    /**
     * @param propertyName
     * @param oldValue
     * @param newValue
     */
    public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
      PropertyChangeSupport pcs;
      synchronized (this) {
        pcs = propertyChangeSupport;
      }
      if (pcs != null && (oldValue != null || newValue != null)) {
        pcs.firePropertyChange(propertyName, oldValue, newValue);
      }
    }


所有注册的监听器实现PropertyChangeListener接口,该接口中有一个方法。


public class RuntimeCfg implements PropertyChangeListener {
     //部分代码省略

        /**
         * Handles changes to the Configuration this RuntimeCfg backs
         * @param evt the PropertyChangeEvent
         */
        public void propertyChange(final PropertyChangeEvent evt) {
            try {
                DynamicProperty.valueOf(evt.getPropertyName()).applyChange(evt, this);
            } catch (IllegalArgumentException e) {
                throw new IllegalStateException(evt.getPropertyName() + " can't be changed dynamically");
            }
        }

}

   再来看看DynamicProperty做了什么。

/**
     * Enum of all properties that can change once the Configuration is being used by a CacheManager
     */
    private static enum DynamicProperty {

        cacheManagerName {
            @Override
            void applyChange(final PropertyChangeEvent evt, final RuntimeCfg config) {
                config.cacheManagerName = (String) evt.getNewValue();
            }
        },
        defaultCacheConfiguration {
            @Override
            void applyChange(final PropertyChangeEvent evt, final RuntimeCfg config) {
                LOG.debug("Default Cache Configuration has changed, previously created caches remain untouched");
            }
        },
        maxBytesLocalHeap {
            @Override
            void applyChange(final PropertyChangeEvent evt, final RuntimeCfg config) {

                ArrayList<ConfigError> errors = new ArrayList<ConfigError>();
                Long newValue = (Long)evt.getNewValue();
                if ((Long) evt.getOldValue() > (Long) evt.getNewValue()) {
                    // Double check for over-allocation again
                    for (Cache cache : getAllActiveCaches(config.cacheManager)) {
                        CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
                        errors.addAll(cacheConfiguration.validateCachePools(config.getConfiguration()));
                        errors.addAll(cacheConfiguration.verifyPoolAllocationsBeforeAddingTo(config.cacheManager,
                            newValue, config.getConfiguration().getMaxBytesLocalOffHeap(), config.getConfiguration().getMaxBytesLocalDisk(), null));
                    }
                }
                if (!errors.isEmpty()) {
                    throw new InvalidConfigurationException("Can't reduce CacheManager byte tuning by so much", errors);
                }
                // Recalculate % based caches
                long cacheAllocated = 0;
                for (Cache cache : getAllActiveCaches(config.cacheManager)) {
                    cache.getCacheConfiguration().configCachePools(config.getConfiguration());
                    long bytesLocalHeap = cache.getCacheConfiguration().getMaxBytesLocalHeap();
                    cacheAllocated += bytesLocalHeap;
                }
                config.cacheManager.getOnHeapPool().setMaxSize(newValue - cacheAllocated);
            }
        },
        maxBytesLocalDisk {
            @Override
            void applyChange(final PropertyChangeEvent evt, final RuntimeCfg config) {
                if ((Long)evt.getOldValue() > (Long)evt.getNewValue()) {
                    // Double check for over-allocation again
                    for (CacheConfiguration cacheConfiguration : config.getConfiguration().getCacheConfigurations().values()) {
                        cacheConfiguration.isMaxBytesLocalDiskPercentageSet();
                    }
                }
                config.cacheManager.getOnDiskPool().setMaxSize((Long) evt.getNewValue());
                // Recalculate % based caches ?
            }
        };

        abstract void applyChange(PropertyChangeEvent evt, RuntimeCfg config);
    }



    使用这个类管理监听器的好处是,它是线程安全的。如果使用一个循环体来set Bean的属性,则这个类可以保证所有监听器执行触发事件的有序。 还有一个好处是,这个类支持 fire 带索引的属性改变事件(详见 java.bean.IndexedPropertyChangeEvent )。此时向注册的监听器发送一个 PropertyChangeEvent 的方法为:

void fireIndexedPropertyChange(String PropertyName,int index,Object oldValue,Object newValue);




© 著作权归作者所有

共有 人打赏支持
ZooKeeper
粉丝 52
博文 27
码字总数 13680
作品 0
杭州
程序员
加载中

评论(2)

ZooKeeper
ZooKeeper

引用来自“Silencer”的评论

很棒

6谢谢!
Silencer
Silencer
很棒
深入理解Ehcache系列(三)

在系列(一)中,提到Ehcache提供了三种清空策略.那么如何设置相应的参数呢? Ehcache提供了配置文件的方式,也提供了参数传递的方式. 配置文件src/config/cache.xml <cache name="testCache"max...

ZooKeeper
2013/12/17
2.3K
3
深入理解MySQL 5.7 GTID系列(九):实际案例一

导 读 作者:高鹏(重庆八怪) 原文地址: https://www.jianshu.com/p/2c25842d58d3 深入理解MySQL 5.7 GTID系列文章共十篇,本文为第四篇,点击查看: 第一篇:深入理解MySQL 5.7 GTID系列(...

老叶茶馆
04/13
0
0
深入理解Ehcache系列(一)

EHcache是 Java最广泛使用的一种Cache. 它能高效的减轻数据库的负载,同时有很好的扩展,支持集群, 是解决C10K问题的一把重要利器. 它使用简单,高速,实现线程安全,同时提供了用内存,磁盘文件...

ZooKeeper
2013/12/16
0
3
深入理解Ehcache系列(二)

CacheManager是Ehcache的缓存主要管理类.支持单例模式和工厂模式. 主要用于管理Ehcache里面有的Cache. 可以使用CacheManager来创建Cache. 如: CacheManager manager = CacheManager.newInst...

ZooKeeper
2013/12/16
0
0
深入理解MySQL 5.7 GTID系列(十):实际案例二

导 读 作者:高鹏(重庆八怪) 原文地址: https://www.jianshu.com/p/2c25842d58d3 深入理解MySQL 5.7 GTID系列文章共十篇,本文为第四篇,点击查看: 第一篇:深入理解MySQL 5.7 GTID系列(...

老叶茶馆
04/25
0
0
深度学习库比较

深度学习库比较 1.TensorFlow 的优点是: 1.1 TensorFlow 的限制 1.2 ensorFlow工作流程 1.3 入门教程 TensorFlow入门一-小石头的码疯窝 TensorFlow之深入理解Neural Style TensorFlow之深入...

刘玉刚
2017/04/16
0
0
深入理解MySQL 5.7 GTID系列(一)

MySQL GTID特性是5.6加入的一个强大的特性,它的目的在于使用GTID的MySQL能够在整个复制环境中能够自动地切换,而不像以前需要指定文件和位置,这也一定是未来发展的方向,我们熟知的MGR也是...

技术小能手
01/08
0
0
深入理解Ehcache系列(五)

Ehcache中可以使用Cache来保存需要缓存的对像,但需要把对象封装在Element的实例里。 往Cache中添加对像: CacheManager manager = CacheManager.newInstance("src/config/cache.xml"); man...

ZooKeeper
2013/12/19
0
0
《深入理解JavaScript系列》系列技术文章整理收藏

《深入理解JavaScript系列》系列技术文章整理收藏 深入理解JavaScript系列来自汤姆大叔的整理贴,原文地址http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html 此处收藏供JavaScr...

开元中国2015
2015/06/22
202
3
BigMemory系列文章--目录

转载请注明出处哈:http://carlosfu.iteye.com/blog/2237511 BigMemory系列文章: BigMemory系列文章--1. Ehcache是什么 BigMemory系列文章--2. Ehcache快速接入 BigMemory系列文章--3. Ehca...

付磊-起扬
2015/08/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

设计模式:单例模式

单例模式的定义是确保某个类在任何情况下都只有一个实例,并且需要提供一个全局的访问点供调用者访问该实例的一种模式。 实现以上模式基于以下必须遵守的两点: 1.构造方法私有化 2.提供一个...

人觉非常君
14分钟前
0
0
《Linux Perf Master》Edition 0.4 发布

在线阅读:https://riboseyim.gitbook.io/perf 在线阅读:https://www.gitbook.com/book/riboseyim/linux-perf-master/details 百度网盘【pdf、mobi、ePub】:https://pan.baidu.com/s/1C20T......

RiboseYim
25分钟前
0
0
conda 换源

https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/conda config --add channels https://mir......

阿豪boy
34分钟前
0
0
Confluence 6 安装补丁类文件

Atlassian 支持或者 Atlassian 缺陷修复小组可能针对有一些关键问题会提供补丁来解决这些问题,但是这些问题还没有放到下一个更新版本中。这些问题将会使用 Class 类文件同时在官方 Jira bug...

honeymose
44分钟前
0
0
非常实用的IDEA插件之总结

1、Alibaba Java Coding Guidelines 经过247天的持续研发,阿里巴巴于10月14日在杭州云栖大会上,正式发布众所期待的《阿里巴巴Java开发规约》扫描插件!该插件由阿里巴巴P3C项目组研发。P3C...

Gibbons
52分钟前
0
0
Tomcat介绍,安装jdk,安装tomcat,配置Tomcat监听80端口

Tomcat介绍 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。 java程序写的网站用tomcat+jdk来运行...

TaoXu
53分钟前
0
0
TensorFlow,从一个 Android Demo 开始

TensorFlow Android Demo 项目地址 Machine Learning 既然提到了 TensorFlow,那是不是得神经网络、机器学习了解下? 如果你能坚持把 机器学习速成课程 给啃完了,觉得还挺有兴趣的,那可以考...

孟飞阳
54分钟前
0
0
JVM学习笔记二:内存结构规范

1、JVM基本结构图 2、java堆(Heap) 3、方法区(Method Area) 4、程序计数器 5、JAVA栈图解 局部变量表:八大基本类型,还可以存储引用类型 上一篇:JVM学习笔记一:类加载机制介绍...

刘祖鹏
今天
0
0
mui集成微信H5支付(返回白屏问题已经解决)

一.项目需求 因为公司人员缺少,没有专门开发安卓和ios的人员,为了项目尽早上线采用了混合APP开发的方式,我选择了MUI混合开发框架,项目中需要在用户购买VIP会员的时候进行支付,所以需要在项目...

银装素裹
今天
1
0
SpringBoot集成Redis--配置自定义的RedisCacheManager

配置自定义的RedisCacheManager--1自定义键生成规则 默认的键生成器 当不指定缓存的key时,SpringBoot会使用SimpleKeyGenerator生成key。 SimpleKeyGenerator SimpleKey 查看源码可以发现,它...

karma123
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部