首页

分析apache mina核心包中实现键值关系对象Map超时对象自动失效的ExpiringMap的源码

标签:mina-core,超时map,自动回收,apache,ExpiringMap,map自定义实现     发布时间:2017-12-17   

一、前言

基于mina-core(2.0.4)包中实现的org.apache.mina.util.ExpiringMap实现自定义失效超时Map,用户大数据缓存策略、用户会话超时及有效时间限制等场景,具体源码内容如下所示

二、源码说明

package org.apache.mina.util;@b@@b@import java.util.Collection;@b@import java.util.Iterator;@b@import java.util.Map;@b@import java.util.Map.Entry;@b@import java.util.Set;@b@import java.util.concurrent.ConcurrentHashMap;@b@import java.util.concurrent.CopyOnWriteArrayList;@b@import java.util.concurrent.locks.Lock;@b@import java.util.concurrent.locks.ReadWriteLock;@b@import java.util.concurrent.locks.ReentrantReadWriteLock;@b@@b@public class ExpiringMap<K, V>@b@  implements Map<K, V>@b@{@b@  public static final int DEFAULT_TIME_TO_LIVE = 60;@b@  public static final int DEFAULT_EXPIRATION_INTERVAL = 1;@b@  private static volatile int expirerCount = 1;@b@  private final ConcurrentHashMap<K, ExpiringMap<K, V>.ExpiringObject> delegate;@b@  private final CopyOnWriteArrayList<ExpirationListener<V>> expirationListeners;@b@  private final ExpiringMap<K, V>.Expirer expirer;@b@@b@  public ExpiringMap()@b@  {@b@    this(60, 1);@b@  }@b@@b@  public ExpiringMap(int timeToLive)@b@  {@b@    this(timeToLive, 1);@b@  }@b@@b@  public ExpiringMap(int timeToLive, int expirationInterval)@b@  {@b@    this(new ConcurrentHashMap(), new CopyOnWriteArrayList(), timeToLive, expirationInterval);@b@  }@b@@b@  private ExpiringMap(ConcurrentHashMap<K, ExpiringMap<K, V>.ExpiringObject> delegate, CopyOnWriteArrayList<ExpirationListener<V>> expirationListeners, int timeToLive, int expirationInterval)@b@  {@b@    this.delegate = delegate;@b@    this.expirationListeners = expirationListeners;@b@@b@    this.expirer = new Expirer(this);@b@    this.expirer.setTimeToLive(timeToLive);@b@    this.expirer.setExpirationInterval(expirationInterval);@b@  }@b@@b@  public V put(K key, V value) {@b@    ExpiringObject answer = (ExpiringObject)this.delegate.put(key, new ExpiringObject(this, key, value, System.currentTimeMillis()));@b@@b@    if (answer == null) {@b@      return null;@b@    }@b@@b@    return answer.getValue();@b@  }@b@@b@  public V get(Object key) {@b@    ExpiringObject object = (ExpiringObject)this.delegate.get(key);@b@@b@    if (object != null) {@b@      object.setLastAccessTime(System.currentTimeMillis());@b@@b@      return object.getValue();@b@    }@b@@b@    return null;@b@  }@b@@b@  public V remove(Object key) {@b@    ExpiringObject answer = (ExpiringObject)this.delegate.remove(key);@b@    if (answer == null) {@b@      return null;@b@    }@b@@b@    return answer.getValue();@b@  }@b@@b@  public boolean containsKey(Object key) {@b@    return this.delegate.containsKey(key);@b@  }@b@@b@  public boolean containsValue(Object value) {@b@    return this.delegate.containsValue(value);@b@  }@b@@b@  public int size() {@b@    return this.delegate.size();@b@  }@b@@b@  public boolean isEmpty() {@b@    return this.delegate.isEmpty();@b@  }@b@@b@  public void clear() {@b@    this.delegate.clear();@b@  }@b@@b@  public int hashCode()@b@  {@b@    return this.delegate.hashCode();@b@  }@b@@b@  public Set<K> keySet() {@b@    return this.delegate.keySet();@b@  }@b@@b@  public boolean equals(Object obj)@b@  {@b@    return this.delegate.equals(obj);@b@  }@b@@b@  public void putAll(Map<? extends K, ? extends V> inMap) {@b@    for (Map.Entry e : inMap.entrySet())@b@      put(e.getKey(), e.getValue());@b@  }@b@@b@  public Collection<V> values()@b@  {@b@    throw new UnsupportedOperationException();@b@  }@b@@b@  public Set<Map.Entry<K, V>> entrySet() {@b@    throw new UnsupportedOperationException();@b@  }@b@@b@  public void addExpirationListener(ExpirationListener<V> listener) {@b@    this.expirationListeners.add(listener);@b@  }@b@@b@  public void removeExpirationListener(ExpirationListener<V> listener)@b@  {@b@    this.expirationListeners.remove(listener);@b@  }@b@@b@  public ExpiringMap<K, V>.Expirer getExpirer() {@b@    return this.expirer;@b@  }@b@@b@  public int getExpirationInterval() {@b@    return this.expirer.getExpirationInterval();@b@  }@b@@b@  public int getTimeToLive() {@b@    return this.expirer.getTimeToLive();@b@  }@b@@b@  public void setExpirationInterval(int expirationInterval) {@b@    this.expirer.setExpirationInterval(expirationInterval);@b@  }@b@@b@  public void setTimeToLive(int timeToLive) {@b@    this.expirer.setTimeToLive(timeToLive);@b@  }@b@@b@  public class Expirer@b@    implements Runnable@b@  {@b@    private final ReadWriteLock stateLock = new ReentrantReadWriteLock();@b@    private long timeToLiveMillis;@b@    private long expirationIntervalMillis;@b@    private boolean running = false;@b@    private final Thread expirerThread;@b@@b@    public Expirer()@b@    {@b@      this.expirerThread = new Thread(this, "ExpiringMapExpirer-" + ExpiringMap.access$008());@b@@b@      this.expirerThread.setDaemon(true);@b@    }@b@@b@    public void run() {@b@      if (this.running) {@b@        processExpires();@b@        try@b@        {@b@          Thread.sleep(this.expirationIntervalMillis);@b@        }@b@        catch (InterruptedException e) {@b@        }@b@      }@b@    }@b@@b@    private void processExpires() {@b@      ExpiringMap.ExpiringObject o;@b@      long timeNow = System.currentTimeMillis();@b@@b@      Iterator i$ = ExpiringMap.access$100(this.this$0).values().iterator();@b@      while (true) { while (true) { if (!(i$.hasNext())) return; o = (ExpiringMap.ExpiringObject)i$.next();@b@@b@          if (this.timeToLiveMillis > 0L)@b@            break;@b@        }@b@@b@        long timeIdle = timeNow - o.getLastAccessTime();@b@@b@        if (timeIdle >= this.timeToLiveMillis) {@b@          ExpiringMap.access$100(this.this$0).remove(o.getKey());@b@@b@          for (ExpirationListener listener : ExpiringMap.access$200(this.this$0))@b@            listener.expired(o.getValue());@b@        }@b@      }@b@    }@b@@b@    public void startExpiring()@b@    {@b@      this.stateLock.writeLock().lock();@b@      try@b@      {@b@        if (!(this.running)) {@b@          this.running = true;@b@          this.expirerThread.start();@b@        }@b@      } finally {@b@        this.stateLock.writeLock().unlock();@b@      }@b@    }@b@@b@    public void startExpiringIfNotStarted()@b@    {@b@      this.stateLock.readLock().lock();@b@      try {@b@        if (this.running)@b@        {@b@          return; } } finally { this.stateLock.readLock().unlock();@b@      }@b@@b@      this.stateLock.writeLock().lock();@b@      try {@b@        if (!(this.running)) {@b@          this.running = true;@b@          this.expirerThread.start();@b@        }@b@      } finally {@b@        this.stateLock.writeLock().unlock();@b@      }@b@    }@b@@b@    public void stopExpiring()@b@    {@b@      this.stateLock.writeLock().lock();@b@      try@b@      {@b@        if (this.running) {@b@          this.running = false;@b@          this.expirerThread.interrupt();@b@        }@b@      } finally {@b@        this.stateLock.writeLock().unlock();@b@      }@b@    }@b@@b@    public boolean isRunning()@b@    {@b@      this.stateLock.readLock().lock();@b@      try@b@      {@b@        boolean bool = this.running;@b@@b@        return bool; } finally { this.stateLock.readLock().unlock();@b@      }@b@    }@b@@b@    public int getTimeToLive()@b@    {@b@      this.stateLock.readLock().lock();@b@      try@b@      {@b@        int i = (int)this.timeToLiveMillis / 1000;@b@@b@        return i; } finally { this.stateLock.readLock().unlock();@b@      }@b@    }@b@@b@    public void setTimeToLive()@b@    {@b@      this.stateLock.writeLock().lock();@b@      try@b@      {@b@        this.timeToLiveMillis = (timeToLive * 1000L);@b@      } finally {@b@        this.stateLock.writeLock().unlock();@b@      }@b@    }@b@@b@    public int getExpirationInterval()@b@    {@b@      this.stateLock.readLock().lock();@b@      try@b@      {@b@        int i = (int)this.expirationIntervalMillis / 1000;@b@@b@        return i; } finally { this.stateLock.readLock().unlock();@b@      }@b@    }@b@@b@    public void setExpirationInterval()@b@    {@b@      this.stateLock.writeLock().lock();@b@      try@b@      {@b@        this.expirationIntervalMillis = (expirationInterval * 1000L);@b@      } finally {@b@        this.stateLock.writeLock().unlock();@b@      }@b@    }@b@  }@b@@b@  private class ExpiringObject@b@  {@b@    private K key;@b@    private V value;@b@    private long lastAccessTime;@b@    private final ReadWriteLock lastAccessTimeLock = new ReentrantReadWriteLock();@b@@b@    ExpiringObject(, V key, long value)@b@    {@b@      if (value == null) {@b@        throw new IllegalArgumentException("An expiring object cannot be null.");@b@      }@b@@b@      this.key = key;@b@      this.value = value;@b@      this.lastAccessTime = lastAccessTime;@b@    }@b@@b@    public long getLastAccessTime() {@b@      this.lastAccessTimeLock.readLock().lock();@b@      try@b@      {@b@        long l = this.lastAccessTime;@b@@b@        return l; } finally { this.lastAccessTimeLock.readLock().unlock();@b@      }@b@    }@b@@b@    public void setLastAccessTime() {@b@      this.lastAccessTimeLock.writeLock().lock();@b@      try@b@      {@b@        this.lastAccessTime = lastAccessTime;@b@      } finally {@b@        this.lastAccessTimeLock.writeLock().unlock();@b@      }@b@    }@b@@b@    public K getKey() {@b@      return this.key;@b@    }@b@@b@    public V getValue() {@b@      return this.value;@b@    }@b@@b@    public boolean equals()@b@    {@b@      return this.value.equals(obj);@b@    }@b@@b@    public int hashCode()@b@    {@b@      return this.value.hashCode();@b@    }@b@  }@b@}
<<热门下载>>