垃圾回收跟踪机制Reference

 
1.Strong Reference以及LRUCache
public class Reference{
    //1M
    private final byte[] data = new byte[2 << 19];
    
    protected void finalize() throws Throwable{
        System.out.println("the reference will be GC");
    }
}
finalize在垃圾回收器对对象标记时调用。但是调用了finalize方法并不代表此类就被回收了。这个类可以自我救赎
 
LRUCache实现:
    LinkedHashMap              ----->双向链表加hashmap
 
public class LRUCache<K,V>{
    //用于记录key值的顺序
    private final LinkedList<K> keyList = new LinkedList<>();
    //用于存储数据
    private final Map<K,V> cache = new HashMap<K,V>();
    //cache最大容量
    private final int capacity;
    //提供一个数据加载方式
    private final CacheLoader<K,V> cacheLoader;
    
    public LRUCache(int capacity,CacheLoader<K,V> cacheLoader){
        this.capacity = capacity;
        this.cacheLoader =cacheLoader;
    }
    
    public void put(K key,V value){
        //容量超过指定容量
        if(keyList.size() >= capacity){
            K eldesKey = keyList.removeFirst();
            cache.remove(eldeKey);
        }
        //list中已经包含了key
        if(keyList.contain(key){
            keyList.remove(key);
        }
        //加入到队尾
              keyList.addLast(key);
             cache.put(key,value);
    }

    public V get(K key){
        //判断list是否包含key
       boolean success = keyList.remove(key);

        if(success){
            keyList.addLast(key);
            return cache.get(key);
        }else{
            //加载value
            V value = cacheLoader.load(key);
            this.put(key,value);
            return value;
        }
    }
}
                                                
 
2.SoftLRUCache实现
当JVM Detect探测到内存即将溢出时。它会尝试回收 SoftReference修饰的对象
public class SoftLRUCache<K,V>{
    //用于记录key值的顺序
    private final LinkedList<K> keyList = new LinkedList<>();
    //用于存储数据
    private final Map<K,SoftReference<V>> cache = new HashMap<K,SoftReference<V>>();
    //cache最大容量
    private final int capacity;
    //提供一个数据加载方式
    private final CacheLoader<K,V> cacheLoader;
    
    public SoftLRUCache(int capacity,CacheLoader<K,V> cacheLoader){
        this.capacity = capacity;
        this.cacheLoader =cacheLoader;
    }
    
    public void put(K key,V value){
        //容量超过指定容量
        if(keyList.size() >= capacity){
            K eldesKey = keyList.removeFirst();
            cache.remove(eldeKey);
        }
        //list中已经包含了key
        if(keyList.contain(key){
            keyList.remove(key);
        }
        //加入到队尾
              keyList.addLast(key);
             cache.put(key,new SoftReference<value>);
    }

    public V get(K key){
        //判断list是否包含key
       boolean success = keyList.remove(key);

        if(success){
            keyList.addLast(key);
            //get()方法返回SoftReference对象的引用,如果为null则表达被来及回收器回收
            return cache.get(key).get();
        }else{
            //加载value
            V value = cacheLoader.load(key);
            this.put(key,value);
            keyList.addLast(key);
            return value;
        }
    }
}
3.WeakReference无论时young GC 还是Full GC都会被回收
1)任何类型的GC都可能导致WeakReference对象被回收
2)获取被垃圾回收器回收的对象
ReferenceQueue<Reference> queue = new Reference<>();
Reference ref = new Reference():
WeakReference<Reference> reference = new WeakReference<>(ref,queue);
//堵塞的方法
java.lang.ref.Reference<? extends Reference> gcedRef = queue.remove();

4.Phantom Reference(虚引用)

1.Phantom Reference必须配合ReferenceQueue使用
2.Phantom Reference的get()方法始终为null
3.当垃圾回收器决定回收Phantom Reference对象时会将其插入关联的Reference Queue中
4.使用Phanto Reference进行清理比垃圾回收器灵活
 
private void release(){
    try{
        if(socket != null){
                socket.close();
        }
    }catch(Throwable e){
            if(socket != null){
                //将socket加入的tracker中
                SocketCleaningTracker.tracker(socket):
            }
    }
}

class SokcetCleaningTracker{

    private static final ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
    
    static{
        //启动Cleaner线程
        new  Cleaner().start();
    }

    private static void track(Socket socket){
        new Trakcer(socket,queue);
    }
    
    private static class Cleaner extends Thread{
        private Cleaner(){
                super("SocketCleaningTracker");
                //防止jvm无法正常关闭
                setDaemon(true);
        }

        public void run(){
            for(;;){

                try{
                    Tracker tracker = (Tracker) queue.remove();
                    tracker.close();
                }catch(InterruptedException e){
                    
                }
            }
        }
    }
//Tracker为Phantom Reference的子类
    private static class Tracker extends PhantomReference<Object>{
        private final Socket socket;

        Tracker(Socket soket,ReferenceQueue<? super Object> queue);
        {
            super(socket,queue);
            this.scoket = socket;
        }
        
        public void colse(){
            try{
                socket.colse();
            }catch(IOException e){
                
            }
        }
    }
}
如同JVM的GC线程的作用一样。不断的从ReferenceQueue中remove Tracker实例
发布了115 篇原创文章 · 获赞 57 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/qq_35211818/article/details/104186441