⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 leastrecentlyusedcache.java

📁 Sequoia ERP是一个真正的企业级开源ERP解决方案。它提供的模块包括:电子商务应用(e-commerce), POS系统(point of sales),知识管理,存货与仓库管理
💻 JAVA
字号:
/* * Licensed under the X license (see http://www.x.org/terms.htm) */package org.ofbiz.minerva.pool.cache;import java.io.PrintWriter;import java.util.*;/** * A Least Recently Used cache implementation.  The object in the * cache that was least recently used is dropped when the cache is * full and a new request comes in.  The implementation uses a linked * list (to track recentness) and a HashMap (to navigate quickly). * @author Aaron Mulder ammulder@alumni.princeton.edu */public class LeastRecentlyUsedCache implements ObjectCache {    private Object lock = new Object();    private HashMap keyMap = new HashMap();    private PrintWriter log = null;    private Node mostRecentNode, leastRecentNode;    private int size;    private int maxSize;    private CachedObjectFactory factory;    public LeastRecentlyUsedCache(CachedObjectFactory factory, int maxSize) {        this.factory = factory;        this.maxSize = maxSize;    }    public Object getObject(Object key) {        return getObject(key, false);    }    public Object useObject(Object key) {        return getObject(key, true);    }    public void returnObject(Object key, Object value) {        Object pooled = keyMap.get(key);        Object source = factory.translateObject(value);        if (pooled == null) {            factory.deleteObject(source);        } else if (pooled instanceof Node) {            Node node = (Node) pooled;            if (node.data == source) {                try {                    node.setUsed(false);                } catch (ConcurrentModificationException e) {                }            } else {                factory.deleteObject(source);            }        } else if (pooled instanceof LinkedList) {            for (Iterator it = ((LinkedList) pooled).iterator(); it.hasNext();) {                Node node = (Node) it.next();                if (node.data == source) {                    try {                        node.setUsed(false);                    } catch (ConcurrentModificationException e) {                    }                    return;                }            }            factory.deleteObject(source);        } else            throw new Error("LRU Cache Assertion Failure: Wrong class '" + pooled.getClass().getName() + "' in keyMap!");    }    public void removeObjects(Object key) {        synchronized (lock) {            Object value = keyMap.get(key);            if (value == null) {                return;            } else if (value instanceof Node) {                removeNode((Node) value);            } else if (value instanceof LinkedList) {                LinkedList list = (LinkedList) value;                int max = list.size();                for (int i = 0; i < max; i++) {                    removeNode((Node) list.get(0));                }            }        }    }    public void setSize(int maxSize) {        this.maxSize = maxSize;        checkMaxSize();    }    public void close() {        synchronized (lock) {            Node current = leastRecentNode;            Node next = current == null ? null : current.moreRecent;            while (current != null) {                removeNode(current);                current = next;                next = current == null ? null : current.moreRecent;            }        }    }    private Object getObject(Object key, boolean use) {        Node node = null;        try {            Object value = keyMap.get(key);            if (value == null) {                node = addObject(key);            } else if (value instanceof Node) {                node = (Node) value;                if (!node.used) {                    makeMostRecent(node);                } else {                    node = addObject(key);                }            } else if (value instanceof LinkedList) {                for (Iterator it = ((LinkedList) value).iterator(); it.hasNext();) {                    node = (Node) it.next();                    if (!node.used) {                        makeMostRecent(node);                        break;                    } else {                        node = null;                    }                }                if (node == null) {                    node = addObject(key);                }            } else                throw new Error("LRU Cache Assertion Failure: Wrong class '" + value.getClass().getName() + "' in keyMap!");            if (use) {                node.setUsed(true);            }        } catch (ConcurrentModificationException e) {            return getObject(key, use);        }        return factory.prepareObject(node.data);    }    private Node addObject(Object key) {        Object data;        try {            data = factory.createObject(key);        } catch (Exception e) {            if (log != null)                e.printStackTrace(log);            return null;        }        Node result;        synchronized (lock) {            if (mostRecentNode == null) {                result = new Node(null, null, data);                mostRecentNode = result;                leastRecentNode = result;            } else {                result = new Node(mostRecentNode, null, data);                mostRecentNode.moreRecent = result;                mostRecentNode = result;            }            ++size;            checkMaxSize();        }        // Put the key/value(s) and node/key in the map        Object value = keyMap.get(key);        if (value == null) {            keyMap.put(key, result);        } else if (value instanceof LinkedList) {            ((LinkedList) value).add(result);        } else if (value instanceof Node) {            LinkedList list = new LinkedList();            list.add(value);            list.add(result);            keyMap.put(key, list);        } else            throw new Error("LRU Cache Assertion Failure: Wrong class '" + value.getClass().getName() + "' in keyMap!");        keyMap.put(result, key);        return result;    }    private void checkMaxSize() {        if (maxSize <= 0)            return;        while (size > maxSize) {            Node drop = leastRecentNode;            leastRecentNode = drop.moreRecent;            leastRecentNode.lessRecent = null;            --size;            removeNode(drop);        }    }    private void makeMostRecent(Node node) {        synchronized (lock) {            if (node.moreRecent == null) {                if (mostRecentNode != node)                    throw new ConcurrentModificationException();                return;            }            // Prepare surrounding nodes            Node previous = node.moreRecent;            Node next = node.lessRecent;            previous.lessRecent = next;            if (next == null) {                leastRecentNode = previous;            } else {                next.moreRecent = previous;            }            // Prepare node and new 2nd most recent            node.moreRecent = null;            node.lessRecent = mostRecentNode;            mostRecentNode.moreRecent = node;            mostRecentNode = node;        }    }    // This should be called while holding the lock    private void removeNode(Node node) {        boolean used = node.used;        if (!used) {            node.used = true;        }        Object key = keyMap.remove(node);        Object value = keyMap.get(key);        if (value instanceof Node) {            keyMap.remove(key);        } else if (value instanceof LinkedList) {            LinkedList list = (LinkedList) value;            Iterator it = list.iterator();            while (it.hasNext()) {                Node current = (Node) it.next();                if (current == node) {                    it.remove();                    break;                }            }            if (list.size() == 1) {                keyMap.put(key, list.get(0));            }        } else            throw new Error("LRU Cache Assertion Failure: Wrong class '" + value.getClass().getName() + "' in keyMap!");        if (!used) {            factory.deleteObject(node.data);        }        node.moreRecent = null;        node.lessRecent = null;    }    private class Node {        Node lessRecent;        Node moreRecent;        Object data;        boolean used = false;        public Node(Node lessRecent, Node moreRecent, Object data) {            this(lessRecent, moreRecent, data, false);        }        public Node(Node lessRecent, Node moreRecent, Object data, boolean used) {            this.lessRecent = lessRecent;            this.moreRecent = moreRecent;            this.data = data;            this.used = used;        }        public synchronized void setUsed(boolean used) {            if (this.used == used)                throw new ConcurrentModificationException();            this.used = used;        }    }/*  This is for testing only    private void printList() {        System.out.print("Fwd Nodes:");        Node node = mostRecentNode;        for(int i=0; i<size; i++) {            System.out.print(" "+node.data);            node = node.lessRecent;        }        System.out.println();        Stack stack = new Stack();        node = leastRecentNode;        for(int i=0; i<size; i++) {            stack.push(node.data);            node = node.moreRecent;        }        System.out.print("Rev Nodes:");        while(!stack.isEmpty())            System.out.print(" "+stack.pop());        System.out.println();    }    public static void main(String args[]) {        try {            java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));            LeastRecentlyUsedCache cache = new LeastRecentlyUsedCache(new CachedObjectFactory() {                public Object createObject(Object identifier) {                    return "v"+identifier;                }                public void deleteObject(Object object) {                    System.out.println("Deleting Object "+object);                }            }, 5);            * *** THIS TESTS getObject ****            while(true) {                cache.printList();                System.out.print("> ");                System.out.flush();                String key = in.readLine();                if(key.equalsIgnoreCase("quit") || key.equalsIgnoreCase("exit"))                    return;                Object value = cache.getObject(key);                System.out.println("Got Value: "+value);            }            * ********* *            **** THIS TESTS useObject AND returnObject ****            Object lastKey = null, last = null;            while(true) {                cache.printList();                System.out.print("> ");                System.out.flush();                String key = in.readLine();                if(key.equalsIgnoreCase("quit") || key.equalsIgnoreCase("exit"))                    return;                Object value = cache.useObject(key);                if(last != null) {                    cache.returnObject(lastKey, last);                }                lastKey = key;                last = value;                System.out.println("Got Value: "+value);            }            ********** *        } catch(Throwable e) {            e.printStackTrace();        }    }*/}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -