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实例