- 浏览: 199785 次
- 性别:
- 来自: 哈尔滨
文章分类
- 全部博客 (267)
- java.lang (8)
- 问题汇总 (21)
- 异常记录 (20)
- 功能实现 (19)
- 面试总结 (25)
- 技巧总结 (8)
- 常用代码 (4)
- 编程习惯 (3)
- 编码规则 (3)
- java.util (10)
- java.io (1)
- JavaWeb (9)
- MySQL (16)
- SVN (3)
- MyBatis (11)
- Velocity (7)
- 其他知识 (10)
- 人生哲理 (1)
- 人生故事 (1)
- 自我感悟 (1)
- shiro (3)
- 基础知识 (0)
- 问题总结 (1)
- Spring 标签 (1)
- Spring (3)
- 点滴生活 (1)
- DOS (1)
- CAS (4)
- Linux (9)
- Storm (6)
- Shell (1)
- regex (1)
- Collection (4)
- poi (1)
- 经典语句 (1)
- NIO (5)
- concurrent (14)
- RPC (1)
- zookeeper (3)
- 待整理 (2)
- Hadoop (9)
- RabbitMq (2)
- flume (1)
- hive (7)
- hbase (4)
- kafka (1)
- scala (1)
- GC (0)
- java.util.concurrent.atomic (1)
- java.lang.ref (6)
- JVM (2)
- algorithm (1)
- conception (1)
- java key word (1)
- sun.misc (1)
最新评论
使用软引用构建敏感数据的缓存
一、实现原理
1.应用场景
查询频率较高的数据;每次查询均需要通过接口与数据库交互,构建对象仍需要占用一部分内存;即便上次查询的结果仍在内存中还未被GC回收但仍需要再次进行相同的查询操作;
将查询结果放入内存--大量占用内存空间,增加发生内存溢出的可能;
每次都重新查询--当前的查询结果使用完毕后,实现的缺陷在于即使垃圾收集线程还没有进行垃圾收集,包含雇员档案信息的对象仍然完好地保存在内存中,应用程序也要重新构建一个对象
折中的方法,能重新获取那些尚未被回收的Java对象的引用,必将减少不必要的访问,大大提高程序的运行速度
2.软引用的特点
对于软引用关联着的对象,如果内存充足,则垃圾回收器不会回收该对象,如果内存不够了,就会回收这些对象的内存
3.软引用配合引用队列
软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
二、代码实现
实现思想
- 工具类使用懒汉模式的单例实现,避免多线程调用时出现问题,对外接口使用synchronized 关键字修饰
- 构建缓存,使用Hashtable,key:存储内容的唯一标识,value:存储对象的软引用实现;取元素时,若此缓存中存在,则说明此时对象未被回收、或已被回收,但软引用在引用队列中未被清除;若无,说明存储的对象已被GC;
- 构建软引用队列,泛型 T 为要存储的对象,当软引用所依赖的对象被GC回收后,JVM将此软引用加入到与之关联的引用队列中。即,此时在等待GC到达 out of memory 前回收此时占用的内存,故每次放入新的对象前,先判断此队列是否有值,若有,主动释放所占用的内存空间
/** * 员工信息类 */ public class Employee { private String id ; // 主键 private String name ; // 姓名 private String department ; // 部门 private Double salary ; // 工资 public Employee(String id){ this.id = id ; } public Employee(String id, String name, String department, Double salary) { super(); this.id = id; this.name = name; this.department = department; this.salary = salary; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; } @Override public String toString() { return "Employee [id=" + id + ", name=" + name + ", department=" + department + ", salary=" + salary + "]"; } }
import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.Hashtable; /** * 员工信息缓存 */ public class EmployeeCache { // 单例模式:懒汉式 private static EmployeeCache employeeCache ; private EmployeeCache(){ // 构造缓存对象时,初始化缓存容器、软索引队列 cache = new Hashtable<String, EmployeeCache.EmployeeRef>(); queue = new ReferenceQueue<Employee>(); } public synchronized static EmployeeCache getInstance(){ if(null == employeeCache){ employeeCache = new EmployeeCache(); } return employeeCache; } // 缓存容器 private static Hashtable<String,EmployeeRef> cache = null; // 软索引队列 private static ReferenceQueue<Employee> queue = null ; /** * 私有内部类:Employee 的软索引对象 */ private class EmployeeRef extends SoftReference<Employee>{ private String uniqueKey = ""; public EmployeeRef(Employee referent, ReferenceQueue<? super Employee> q) { super(referent, q); this.setUniqueKey(referent.getId()); } public void setUniqueKey(String uniqueKey) { this.uniqueKey = uniqueKey; } } /** * 向缓存中添加元素 */ public void put(Employee employee){ // 清空已在引用队列中的软索引对象,释放空间 clearReferenceQueue(); EmployeeRef ref = new EmployeeRef(employee, queue); cache.put(ref.uniqueKey, ref); } private void clearReferenceQueue(){ EmployeeRef ref = null ; // 引用队列中的数据出队列 while((ref = (EmployeeRef)queue.poll()) != null){ // 同时清除该软引用作为KEY的对象内容 cache.remove(ref.uniqueKey); } } /** * 从缓存中取出元素 * @param key * @return */ public Employee get(String key){ Employee employee = null ; if(cache.containsKey(key)){ EmployeeRef employeeRef = cache.get(key); employee = employeeRef.get(); } if(null == employee){ employee = new Employee(key); EmployeeRef ref = new EmployeeRef(employee, queue); cache.put(key, ref); } return employee ; } }
public class EmployeeCacheMain { private static EmployeeCache cache = EmployeeCache.getInstance(); /** * @param args */ public static void main(String[] args) { Employee e1 = new Employee("1", "张三", "测试部门", 10000.0); Employee e2 = new Employee("2", "李四", "开发部门", 15000.0); cache.put(e1); cache.put(e2); Employee employee = cache.get("1"); System.out.println(employee.toString()); e2.setDepartment("测试部门"); cache.put(e2); System.out.println(cache.get("2").getDepartment()); } }
博文参考:
java引用类型
浅谈java对象引用及对象赋值
发表评论
-
JSP自定义标签
2017-11-14 20:35 308JSP页面中分页功能实现使用了 <urlChange ... -
手机号码替换中间四位
2017-10-24 21:41 891需求描述: 为用户隐私考虑,展示用户信息时需要将中间用*代替 ... -
遍历集合删除元素
2017-10-24 18:44 611一、根据下标删除元素 1.测试代码 ArrayLis ... -
统计每天的数据
2017-10-10 21:23 498需求:按天统计数据 分析:create_time 为 dat ... -
基于AbstractDataSource实现主从数据库切换
2017-10-07 18:03 981基于AbstractDataSource实现主从数据库切换 ... -
服务器文件下载
2016-03-27 09:53 343项目需求:在列表页面上提供文件下载链接 项目实现: 1.准 ... -
扫码登录功能实现
2015-08-21 08:19 486需求:PC端(电脑端) ... -
基于SHIRO实现用户登陆后跳转其匿名访问的URL路径
2015-07-15 15:03 3579需求描述: 用户在未登录时访问网站中某个需要登录后才能访问 ... -
基于SHIRO的管理后台权限认证系统实现(一)
2015-07-09 10:05 6943基于SHIRO的管理后台权限认证系统实现(一) 一、项目需求 ... -
基于SHIRO的管理后台权限认证系统实现(二)
2015-06-28 10:14 780用户登陆系统后左侧菜单加载 项目:管理员系统 功能:用户登 ... -
Velocity中set的使用
2015-05-26 10:46 494问题:从页面接收某字段的提交数据,数据要求是组合后的编号 ... -
Velocity页面中输出时间年月
2015-05-19 20:52 940问题:注册页面要求有创建时间的选项添加,年为至今为止 实现: ... -
Set判重操作实现
2015-05-15 15:28 759需求:Set<Po>判重操作实现 问题:Set& ... -
如何去除List集合中的重复数据
2015-05-15 13:12 872需求:用户权限查看, ... -
Date相关功能实现
2015-05-12 19:47 586一、同一天 需求:用户记录跟踪列表展示,要求用户数据同一天内 ... -
velocity截取过长的字段值
2015-05-11 20:06 333问题:页面列表展示时,某个字段的值超长,影响页面的整体样式 ... -
将list中某个元素放在首位
2015-05-10 17:25 4500需求:程序开发过程中,业务方要求在展示国家列表时要将US放在首 ... -
Velocity遍历map与遍历list
2015-04-22 20:16 6893问题: 向页面传递key与value的组合 1. 1.1 ...
相关推荐
11.3 数据缓存 11.3.1 向缓存添加项目 11.3.2 简单的缓存测试 11.3.3 缓存优先级 11.3.4 使用数据源控件的缓存 11.4 缓存依赖 11.4.1 文件和缓存项目依赖 11.4.2 聚合依赖 11.4.3 移除项目回调 ...
11.3 数据缓存 373 11.3.1 向缓存添加项目 373 11.3.2 简单的缓存测试 375 11.3.3 缓存优先级 376 11.3.4 使用数据源控件的缓存 376 11.4 缓存依赖 379 11.4.1 文件和缓存项目依赖 379 11.4.2 聚合...
10.12. 使用元数据 11. 事务和并发 11.1. Session和事务范围(transaction scope) 11.1.1. 操作单元(Unit of work) 11.1.2. 长对话 11.1.3. 关注对象标识(Considering object identity) 11.1.4. 常见问题 11.2...
10.12. 使用元数据 11. 事务和并发 11.1. Session和事务范围(transaction scope) 11.1.1. 操作单元(Unit of work) 11.1.2. 长对话 11.1.3. 关注对象标识(Considering object identity) 11.1.4. 常见问题 11.2...
10.12. 使用元数据 11. 事务和并发 11.1. Session和事务范围(transaction scope) 11.1.1. 操作单元(Unit of work) 11.1.2. 长对话 11.1.3. 关注对象标识(Considering object identity) 11.1.4. 常见问题 11.2...
10.12. 使用元数据 11. 事务和并发 11.1. Session和事务范围(transaction scope) 11.1.1. 操作单元(Unit of work) 11.1.2. 长对话 11.1.3. 关注对象标识(Considering object identity) 11.1.4. 常见问题 11.2...
使用元数据 11. 事务和并发 11.1. Session和事务范围(transaction scope) 11.1.1. 操作单元(Unit of work) 11.1.2. 长对话 11.1.3. 关注对象标识(Considering object identity) 11.1.4. 常见问题 11.2. ...
10.12. 使用元数据 11. 事务和并发 11.1. Session和事务范围(transaction scope) 11.1.1. 操作单元(Unit of work) 11.1.2. 长对话 11.1.3. 关注对象标识(Considering object identity) 11.1.4. 常见问题 11.2. ...
10.12. 使用元数据 11. 事务和并发 11.1. Session和事务范围(transaction scope) 11.1.1. 操作单元(Unit of work) 11.1.2. 长对话 11.1.3. 关注对象标识(Considering object identity) 11.1.4. 常见问题 11.2. ...
7.2 使用pickle和cPickle模块序列化数据 277 7.3 在Pickling的时候压缩 280 7.4 对类和实例使用cPickle模块 281 7.5 Pickling被绑定方法 284 7.6 Pickling代码对象 286 7.7 通过shelve修改对象 288 7.8 使用...
16.2.1 访问或修改敏感数据 16.2.2 数据丢失或破坏 16.2.3 拒绝服务 16.2.4 恶意代码注入 16.2.5 服务器被攻破 16.3了解与我们“打交道”的用户 16.3.1 破解人员 16.3.2 受影响机器的未知情用户 16.3.3 对公司不满的...
16.2.1 访问或修改敏感数据 16.2.2 数据丢失或破坏 16.2.3 拒绝服务 16.2.4 恶意代码注入 16.2.5 服务器被攻破 16.3了解与我们“打交道”的用户 16.3.1 破解人员 16.3.2 受影响机器的未知情用户 16.3.3 对公司不满的...
16.2.1 访问或修改敏感数据 16.2.2 数据丢失或破坏 16.2.3 拒绝服务 16.2.4 恶意代码注入 16.2.5 服务器被攻破 16.3了解与我们“打交道”的用户 16.3.1 破解人员 16.3.2 受影响机器的未知情用户 16.3.3 对公司不满的...
10.12. 使用元数据 11. 事务和并发 11.1. Session和事务范围(transaction scope) 11.1.1. 操作单元(Unit of work) 11.1.2. 长对话 11.1.3. 关注对象标识(Considering object identity) 11.1.4. 常见问题 11.2...
理解DataSet的数据缓存机制 存储过程 可按任意字段排序的分页存储过程(不用临时表的方法,不看全文会后悔) 常用sql存储过程集锦 存储过程中实现类似split功能(charindex) 通过查询系统表得到纵向的表结构 将数据库表...
19.5 自引用的连接 287 19.6 Acts As 288 19.7 何时保存 291 19.8 预先读取子记录 292 19.9 计数器 293 第20章 ActiveRecord第三部分:对象生命周期 295 20.1 校验 295 20.2 回调 303 20.3 高级属性 308 20.4 事务 ...
16.2 使用名字空间 .200 16.3 使用指示符 .203 16.4 程 序 示 例 .206 16.5 小 结 .213 第十七章 文 件 操 作 .215 17.1 .Net 框架结构提供的 I/O 方式 .215 17.2 文件存储管理 .217 17.3 读 写 文 件...