1.LRUCacheWithListener :逻辑在这里实现
对象缓冲池---采用最近最久未使用策略管理对象,同时带有事件监听功能
工作原理:
采用集合框架(java.connection包)来实现最近最久未使用对象池
首先构造对象池、设置池的大小
放置对象到池中,保存时候,池的指针指向该对象,以表明该对象最近最短被使用过
当把新的对象放入到池中时候,池已经满,那把删除最久没有被使用的对象,然后放入对象
当从池中读取对象时候,根据条件从池中获得对象;然后把池的指针指向该取出的对象,以表明该对象最近最短被使用过
当池中有对象被清除时候(当成垃圾清除),会触发相关事件
当池被清空时候,会出发相关事件
这个类参考了org.apache.tomcat.util.collections.LRUCache的实现细节。
当然原代码采用Hashtable来存储池的对象列表,这里采用另外的存储方式---HashMap来存储
org.apache.tomcat.util.collections.LRUCache
文件位置:jakarta-tomcat-5.5.6\jakarta-tomcat-connectors\util
import java.util.*;
public class LRUCacheWithListener {
/**
* 池对象的包裹类,这样便于相关处理
* **/
class CacheNode {
CacheNode prev;
CacheNode next;
Abandon value;
Object key;
public CacheNode() {
}
}
/**
* 对象池大小
**/
private int cacheSize;
/**
* 对象列表、当然可以采用泛型编程,这样就实现自动装箱、解箱(boxing/unboxing)
* **/
private HashMap nodes;
/**
* 对象池当前对象数
* **/
private int currentSize;
/**
* 第一个节点
* **/
private CacheNode first;
/***
* 最后一个节点
* **/
private CacheNode last;
/**
* 对象锁
* 实际上下面也就几个地方使用了该锁,可以用同步方法来取代调使用这个对象锁
* **/
private static int DEFAULT_SIZE = 10;
public LRUCacheWithListener() {
this(DEFAULT_SIZE);
}
public LRUCacheWithListener(int poolSize) {
cacheSize = poolSize;
currentSize = 0;
first = null; //
last = null; //
nodes = new HashMap(poolSize);
}
/**
* 读取一个对象
* ***/
public synchronized Object get(Object key) {
CacheNode node = (CacheNode) nodes.get(key);
if (node != null) {
moveToHead(node);
return node.value;
} else {
return null;
}
}
/**
* 把指定对象移动到链表的头部
* */
private void moveToHead(CacheNode node) {
if (node == first) {
return;
}
if (node.prev != null) {
node.prev.next = node.next;
}
if (node.next != null) {
node.next.prev = node.prev;
}
if (last == node) {
last = node.prev;
}
if (first != null) {
node.next = first;
first.prev = node;
}
first = node;
node.prev = null;
if (last == null) {
last = first;
}
}
/**
* 删除池中指定对象
* **/
public synchronized Object remove(Object key) {
CacheNode node = (CacheNode) nodes.get(key);
if (node != null) {
if (node.prev != null) {
node.prev.next = node.next;
}
if (node.next != null) {
node.next.prev = node.prev;
}
if (last == node) {
last = node.prev;
}
if (first == node) {
first = node.next;
}
}
return node;
}
/****
* 放置一个对象到池中
* */
public synchronized void put(Object key, Abandon value) {
CacheNode node = (CacheNode) nodes.get(key);
if (node == null) {
//池满,删除最久没有使用的对象
if (currentSize >= cacheSize) {
if (last != null) {
nodes.remove(last.key);
}
removeLast();
}
//池没有满,直接把对象放入池中
else {
currentSize++;
}
node = getANewCacheNode();
}
node.value = value;
node.key = key;
// 把放入池的这个对象移动到链表的头部,表示最近最短被使用过
moveToHead(node);
nodes.put(key, node);
}
/**清空池中对象
* **/
public synchronized void clear() {
// if (first != null) {
// Iterator i = nodes.values().iterator();
// //触发事件,该池已经被清空
// CacheNode n;
// while (i.hasNext()) {
// n = (CacheNode) (i.next());
// n.value.poolClear();
// }
// }
while(!nodes.isEmpty()){
//add by jeff
if (last != null) {
nodes.remove(last.key);
}
removeLast(); //从池中将对象一个个移除
}
first = null;
last = null;
}
/***
* 获得一个新的包裹对象
* **/
private CacheNode getANewCacheNode() {
CacheNode node = new CacheNode();
return node;
}
/**
* 删除池中最久没有使用的对象
* **/
private void removeLast() {
if (last != null) {
//对象从池中被抛弃,触发事件
last.value.onAbandon();
if (last.prev != null) {
last.prev.next = null;
} else {
first = null;
}
last = last.prev;
}
}
}
2.Abandon :定义对象被抛弃和池被清空的事件接口
public interface Abandon {
public void onAbandon();
}
3.CacheNodeWithListener 测试类
public class CacheNodeWithListener implements Abandon {
int id;
public CacheNodeWithListener() {
}
public CacheNodeWithListener(int i) {
id = i;
}
/**
* 当对象被池所抛弃时候,进行相关处理
* ***/
public void onAbandon() {
System.out.println(this +"---onAbandon()");
}
public String toString() {
return "id=" + id;
}
static public void main(String[] s) {
LRUCacheWithListener pool = new LRUCacheWithListener(3); //LRUCacheWithListener(int poolSize) 对象池大小
int i;
for (i = 1; i <= 5; i++) {
pool.put("obj" + i, new CacheNodeWithListener(i));
System.out.println("obj--"+i);
}
System.out.println("obj"+4+":"+pool.get("obj"+4));
pool.clear();//把 《对象池全清空》,poolSize有多大清多少
//检查pool里的对象是否全清掉
for (i = 1; i <= 5; i++) {
System.out.println("obj"+i+":"+pool.get("obj"+i));
}
}
}
4.结论:打印结果
当poolSize为3,而有5个对象需要加入,打印结果如下:
obj--1
obj--2
obj--3
id=1---onAbandon()
obj--4
id=2---onAbandon()
obj--5
obj4:id=4
id=3---onAbandon()
id=5---onAbandon()
id=4---onAbandon()
obj1:null
obj2:null
obj3:null
obj4:null
obj5:null
解析:先放入3个对象,第四个对象加入时抛弃最先加入的对象1
第五个对象加入时抛弃最二先加入的对象2,最后clear就把
内存中的3,4,5清掉
分享到:
相关推荐
2. **缓冲池管理**:创建一个管理类来维护整个缓冲池,包括初始化缓冲池(分配内存并初始化缓冲区对象)、获取空闲缓冲区(从池中取出未被使用的缓冲区)、归还缓冲区(将使用完的缓冲区放回池中)和释放缓冲池...
### 操作系统中缓冲池的模拟使用:深入解析与实践 #### 缓冲池概念与作用 在操作系统中,缓冲池是一种用于缓存数据的重要机制,它能够有效地提高数据读写效率,减少对磁盘或其他外部存储设备的访问次数,从而优化...
对象池是一种内存管理策略,它预先创建并存储一组对象,当需要时可以从池中获取,而不是每次都新建,从而避免了频繁的内存分配和释放操作。 在UE4中,"Actor"是游戏世界中的基本元素,可以是角色、物体、环境等任何...
在这个"缓冲池的简单模拟-操作系统课程设计"中,开发者使用了VC++作为编程环境,创建了一个简单的缓冲池模型,尽管它并未实现并发处理。 在VC++中,我们可以使用标准模板库(STL)中的容器,如vector或queue,来模拟...
7. **内存池**:缓冲池常常是内存池策略的一部分,内存池包括了缓冲池和其他内存管理策略,如对象池,它们都是为了优化内存分配和管理。 在实际开发中,使用缓冲池类可以显著提升程序的性能,特别是在大量小对象...
3. **缓存替换策略**:根据实际需求,可能需要实现不同的缓存替换策略,如LRU(最近最少使用)、LFU(最不经常使用)等,以优化缓冲区的使用效率。 4. **性能监控**:添加统计信息,如缓冲区的使用率、等待时间等,...
在Windows操作系统中,缓冲池是一种内存管理机制,用于优化系统对内存资源的分配和使用,尤其是在处理并发和多线程环境时。缓冲池的核心概念是将内存分配过程集中化,减少碎片并提高效率。本代码实现了一个特定的...
在这款引擎中,对象缓冲池(Object Pool)是一个优化资源管理的重要概念,它能够有效地提高游戏性能,避免频繁地创建和销毁对象带来的开销。本文将深入探讨Cocos2d-js-v3.6中对象缓冲池的使用及其背后的原理。 在...
2. **内存管理**:缓冲池有助于减少内存碎片化的问题,同时减少了GC(垃圾回收)的压力,因为对象被重复利用而不是频繁地创建和销毁。 3. **性能提升**:通过减少对象创建的数量,可以有效降低CPU的负载,进而提高...
在提供的文件“MultiBuffer”中,可能包含了实现这样一个缓冲池的代码,包括缓冲区对象的创建、管理和读写线程间的协作逻辑。通过分析这个代码,我们可以深入理解缓冲池的工作原理以及如何在实际项目中应用它。 ...
Java对象缓冲实现中间件是一种高效的数据存储和访问机制,它通过在内存中创建一个对象池来减少对硬盘或网络资源的频繁访问,从而提高应用程序的性能。这种中间件设计的核心理念是利用内存的高速访问特性,将常用或者...
《轻量级的对象池》 ...通过合理设计和使用对象池,我们可以有效地管理资源,提高系统运行效率,同时降低内存消耗和系统负载。理解和掌握对象池的原理和实现,对于优化代码和提升软件性能具有重要意义。
在编程领域,尤其是在性能敏感的系统中,对象池是一种优化技术,用于管理和重用对象,以减少频繁创建和销毁对象带来的开销。本课件主要围绕C#中的对象池进行讲解,旨在帮助开发者理解并掌握这一高效编程策略。 C#的...
3. **对象状态管理**:每个对象需要有一个状态标识,表示其是否正在使用,以便正确地处理对象的获取和释放。 四、对象池在游戏开发中的应用 1. **游戏对象复用**:例如,游戏中子弹、粒子效果等短暂存在且频繁创建...
缓冲池(Buffer Pool)是一种内存管理策略,它预先分配一部分内存,供多个线程共享,避免了频繁地申请和释放内存,从而提高了系统的效率。 在Java中,缓冲池主要体现在NIO(New IO)框架中,特别是Java NIO 2引入的...
【缓冲池模拟及实现】 缓冲池是操作系统中用于提高...总的来说,这个实验让学生通过实际操作理解了缓冲池的概念,掌握了如何使用线程和同步机制来管理共享资源,对操作系统中的并发处理和资源调度有了更深入的认识。
LRU 策略就是依据数据的访问时间来决定其生存状态,最新访问的数据会被保留,而最早访问且长时间未再使用的数据则会被优先淘汰。 Java 中实现 LRU 缓存的一个常见方法是利用 `LinkedHashMap` 类。`LinkedHashMap` ...
本Demo主要关注VideoView在播放过程中可能出现的缓冲和卡顿问题,以及如何通过监听和处理来优化用户体验。 一、VideoView缓冲与卡顿监听 1. 缓冲监听: 当VideoView从网络加载视频数据时,可能会因为网络状况不佳...
本文将详细介绍EAServer 6.x数据库缓冲池的配置方法,帮助开发者更好地理解和使用这一功能。 #### 二、EAServer 6.x简介 Sybase EAServer 6.x是一款由Sybase公司开发的企业级应用服务器,它支持多种编程语言和技术...
本篇将深入探讨如何监听VideoView的缓冲状态、实时显示下载速度,并实现大小屏切换的功能。 首先,我们来看如何监听VideoView的缓冲状态。VideoView并没有直接提供缓冲监听接口,但我们可以利用SurfaceHolder的回调...