科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道对象缓冲池--采用最近最久未使用策略(LRUCache )管理对象,同时带有事件监听功能[改正版]

对象缓冲池--采用最近最久未使用策略(LRUCache )管理对象,同时带有事件监听功能[改正版]

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

对象缓冲池---采用最近最久未使用策略管理对象,同时带有事件监听功能 工作原理:

作者:民 来源:CSDN 2008年3月17日

关键字: 监听 事件 java

  • 评论
  • 分享微博
  • 分享邮件

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清掉

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章