📄 abstractreferencecache.java
字号:
// You can redistribute this software and/or modify it under the terms of// the Ozone Core License version 1 published by ozone-db.org.//// Copyright (C) 2003-@year@, Leo Mekenkamp. All rights reserved.//// $Id: AbstractReferenceCache.java,v 1.2.2.2 2004/04/10 10:06:51 per_nyfelt Exp $package org.ozoneDB.core.storage;import java.lang.ref.Reference;import java.lang.ref.ReferenceQueue;import java.lang.ref.SoftReference;import java.util.Collection;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.LinkedList;import java.util.Map;import java.util.Map.Entry;import java.util.Properties;import java.util.Set;/** * * @author <a href="mailto:leoATmekenkampD0Tcom">Leo Mekenkamp (mind the anti sp@m)</a> * @version $Id: AbstractReferenceCache.java,v 1.2.2.2 2004/04/10 10:06:51 per_nyfelt Exp $ */public abstract class AbstractReferenceCache implements Cache, PropertyConfigurable { /** * We need to find objects in the map that holds the references. To do that * we need to add a key to a reference. The ReferenceHandler can * remove defunct references from the map, using the key to find the * defunct references. */ protected interface KeyedReference { public void clear(); public boolean enqueue(); public Object get(); public boolean isEnqueued(); public Object getKey(); } /** * Handles the garbage collector 'messages' that certain softly reachable * objects have been gc-ed. * The <code>ObjectReference</code> instances that pointed to them * are removed from the backing map in order to prevent the backing map to * overflow with soft reference instances that now point to null. */ private class ReferenceHandler extends Thread { ReferenceHandler() { super(Thread.currentThread().getThreadGroup(), "stale reference remover"); setDaemon(true); setPriority(Thread.MAX_PRIORITY - 1); } public void run() { for(;;) { try { KeyedReference ref = (KeyedReference) getReferenceQueue().remove(); Set keys = new HashSet(); keys.add(ref.getKey()); // The gc seems to enqueue in bulk; this is also the reason // to use multiple threads instead of one static thread: in // the latter case we would have to synchronize on different // caches: now we can suffice with just one synchronized // block. As long as the number of abstract caches stays low // perfomance is a lot better. while ((ref = (KeyedReference) getReferenceQueue().poll()) != null) { keys.add(ref.getKey()); } synchronized(AbstractReferenceCache.this) { getMap().keySet().removeAll(keys); } } catch (InterruptedException ignore) { } } } } // ReferenceHandler private ReferenceQueue referenceQueue; private ReferenceHandler referenceHandler; private String prefix; /** * backing map (key -> (ObjectReference -> cached object)) */ private Map map; public AbstractReferenceCache(Properties properties, String prefix) { this.prefix = prefix; map = new LinkedHashMap(); referenceQueue = new ReferenceQueue(); referenceHandler = new ReferenceHandler(); referenceHandler.start(); } protected abstract KeyedReference createKeyedReference(Object key, Object value, ReferenceQueue referenceQueue); public synchronized Object get(Object key) { KeyedReference ref = (KeyedReference) getMap().get(key); return ref == null ? null : ref.get(); } public synchronized void put(Object key, Object value) { KeyedReference ref = createKeyedReference(key, value, getReferenceQueue()); getMap().put(key, ref); } public synchronized Object remove(Object key) { KeyedReference ref = (KeyedReference) getMap().remove(key); return ref == null ? null : ref.get(); } public synchronized Map copyToMap() { Map result = new HashMap(); for (Iterator i = getMap().entrySet().iterator(); i.hasNext(); ) { Entry entry = (Entry) i.next(); KeyedReference ref = (KeyedReference) entry.getValue(); Object value = ref.get(); if (value != null) { result.put(entry.getKey(), value); } } return result; } // private so it can be inlined private Map getMap() { return map; } // private so it can be inlined private ReferenceQueue getReferenceQueue() { return referenceQueue; } public synchronized int size() { return getMap().size(); } public String getPrefix() { return prefix; } public Collection getPropertyInfos() { return new LinkedList(); } // debug code only following protected AbstractReferenceCache() { } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -