java 缓冲

import org.apache.log4j.Logger;

import java.lang.management.ManagementFactory;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 基于SoftReference做缓存,内存不足时自动回收。
 * 线程安全性待测试。
 * User: linannan
 * Date: 12-4-9
 * Time: 下午4:47
 */
public class SoftCache<K, V> {
    protected static final Logger logger = Logger.getLogger(SoftCache.class);
    private final ReferenceQueue queue;
    private final Map<K, CacheEntry<K, V>> cache;
    /**
     * get取出后,避免被立即回收。
     */
    private final LinkedList<V> hardLinksToAvoidGarbageCollection;
    private int hardLinksNumber;

    public SoftCache() {
        queue = new ReferenceQueue();
        cache = new ConcurrentHashMap<K, CacheEntry<K, V>>();
        hardLinksToAvoidGarbageCollection = new LinkedList<V>();
        hardLinksNumber = 256;
    }


    public void put(K key, V value) {
        removeGarbageItems();
        cache.put(key, new CacheEntry(key, value, queue));
    }

    public V get(K key) {
        CacheEntry<K, V> entry = cache.get(key);
        if (entry == null) {
            return null;
        } else {
            V value = entry.get();
            if (value == null) {
                cache.remove(key);
            } else {
                /**
                 * 增加一个强引用,免得被回收了
                 */
                hardLinksToAvoidGarbageCollection.addFirst(value);
                if (hardLinksToAvoidGarbageCollection.size() > hardLinksNumber) {
                    hardLinksToAvoidGarbageCollection.removeLast();
                }
                return value;
            }
        }
        return null;
    }

    /**
     * 清空缓存
     */
    public void clear() {
        hardLinksToAvoidGarbageCollection.clear();
        removeGarbageItems();
        cache.clear();
    }

    /**
     * 删除已经被回收掉的
     */
    public void removeGarbageItems() {
        Reference r = null;
        while ((r = queue.poll()) != null) {
            CacheEntry entry = (CacheEntry) r;
            logger.debug("内存不足,remove->" + entry.key);
            cache.remove(entry.key);
        }
    }

    public int size() {
        removeGarbageItems();
        return cache.size();
    }

    public Set<K> keySet(){
        return cache.keySet();
    }

    private static class CacheEntry<K, V> extends SoftReference<V> {
        K key;

        public CacheEntry(K key, V value, ReferenceQueue queue) {
            super(value, queue);
            this.key = key;
        }
    }


    public static void main(String[] args) throws InterruptedException {
        System.out.println("test");

        SoftCache cache = new SoftCache();
        for (int i = 0; i < 2000000; i++) {
            try {
                cache.put("" + i, "" + i);
            } catch (OutOfMemoryError error) {
                System.out.println(error.getMessage());
                System.gc();
            }
        }
        System.out.println(ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() / 1000 / 1000);
        System.out.println(cache.size());
        System.gc();
        System.out.println(cache.size());

        Thread.sleep(2000);

        System.gc();
        Thread.sleep(2000);
        System.out.println(ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() / 1000 / 1000);
        System.gc();
        System.out.println(cache.size());
    }


}

你可能感兴趣的:(java)