java.util.concurrentを使用して、オブジェクトの特定のストレージ時間でキャッシュを書き込みます

少し前までは、一定の時間が経過すると自動的にキャッシュを消去するタスクを作成しました。 要件は次のとおりです。

  1. 軽量
  2. スレッドセーフ


それだけです。 このタスクをjava.util.concurrentで書く前は対処していませんでした。 このパッケージを使用するというアイデアは、同僚の1人によって促されました。同僚は似たようなものを持っていましたが、必要な機能とは一致しませんでした。 それでは、始めましょう:



キーは内部クラスになり、その直接的な目的に加えて、その存在が終了したため、「ライブ」であるか、キャッシュから削除できるかを決定します。



private static class Key { private final Object key; private final long timelife; public Key(Object key, long timeout) { this.key = key; this.timelife = System.currentTimeMillis() + timeout; } public Key(Object key) { this.key = key; } public Object getKey() { return key; } public boolean isLive(long currentTimeMillis) { return currentTimeMillis < timelife; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Key other = (Key) obj; if (this.key != other.key && (this.key == null || !this.key.equals(other.key))) { return false; } return true; } @Override public int hashCode() { int hash = 7; hash = 43 * hash + (this.key != null ? this.key.hashCode() : 0); return hash; } @Override public String toString() { return "Key{" + "key=" + key + '}'; } }
      
      







キャッシュクラス自体がパラメーター化されます。 内部にはストレージコンテナが必要です。 java.util.concurrent.ConcurrentHashMapが最適に機能します。 デフォルトのストレージ時間は、別のフィールドによってリースされます。 次に、java.util.concurrent.ScheduledExecutorServiceを作成します。



 public class CacheUtil<K, V> { private ConcurrentHashMap<Key, V> globalMap = new ConcurrentHashMap<Key, V>(); private long default_timeout; private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread th = new Thread(r); th.setDaemon(true); return th; } }); }
      
      





メインスレッドが終了すると、キャッシュをクリアするプロセスも終了するように、スレッドを悪魔にします。



コンストラクターでシェダーを実行します。シェダーは、一定の時間(この場合、オブジェクトの保存時間の5番目の部分です)マップを調べて、有効期限が切れたオブジェクトをすべて削除します。



  public CacheUtil(long default_timeout) throws Exception { if (default_timeout < 100) { throw new Exception("Too short interval for storage in the cache. Interval should be more than 10 ms"); } default_timeout = default_timeout; scheduler.scheduleAtFixedRate(new Runnable() { @Override public void run() { long current = System.currentTimeMillis(); for (Key k : globalMap.keySet()) { if (!k.isLive(current)) { globalMap.remove(k); } } } }, 1, default_timeout/5, TimeUnit.MILLISECONDS); }
      
      







次に、キャッシュを操作するメソッドを追加します-これですべてが使用可能になります。 完全なコードは次のとおりです。



 public class Cahe<K, V> { private volatile ConcurrentHashMap<Key, V> globalMap = new ConcurrentHashMap<Key, V>(); private long default_timeout; private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread th = new Thread(r); th.setDaemon(true); return th; } }); /** * @param default_timeout   -       . */ public Cache(long default_timeout) throws Exception { if (default_timeout < 10) { throw new Exception("Too short interval for storage in the cache. Interval should be more than 10 ms"); } this.default_timeout = default_timeout; scheduler.scheduleAtFixedRate(new Runnable() { @Override public void run() { long current = System.currentTimeMillis(); for (Key k : globalMap.keySet()) { if (!k.isLive(current)) { globalMap.remove(k); } } } }, 1, default_timeout/5, TimeUnit.MILLISECONDS); } /** * @param default_timeout   -        */ public void setDefault_timeout(long default_timeout) throws Exception { if (default_timeout < 100) { throw new Exception("Too short interval for storage in the cache. Interval should be more than 10 ms"); } this.default_timeout = default_timeout; } /** *       *      * @param <K> * @param <V> * @param key    * @param data  */ public void put(K key, V data) { globalMap.put(new Key(key, default_timeout), data); } /** *       * @param <K> * @param <V> * @param key    * @param data  * @param timeout        */ public void put(K key, V data, long timeout) { globalMap.put(new Key(key, timeout), data); } /** *     * @param <K> * @param <V> * @param key      * @return      */ public V get(K key) { return globalMap.get(new Key(key)); } /** *        * @param <K> * @param key -  */ public void remove(K key) { globalMap.remove(new Key(key)); } /** *      */ public void removeAll() { globalMap.clear(); } /** *     . *    . * @param <K> * @param <V> * @param map    */ public void setAll(Map<K, V> map) { ConcurrentHashMap tempmap = new ConcurrentHashMap<Key, V>(); for (Entry<K, V> entry : map.entrySet()) { tempmap.put(new Key(entry.getKey(), default_timeout), entry.getValue()); } globalMap = tempmap; } /** *       *    . * @param <K> * @param <V> * @param map    */ public void addAll(Map<K, V> map) { for (Entry<K, V> entry : map.entrySet()) { put(entry.getKey(), entry.getValue()); } } private static class Key { private final Object key; private final long timelife; public Key(Object key, long timeout) { this.key = key; this.timelife = System.currentTimeMillis() + timeout; } public Key(Object key) { this.key = key; } public Object getKey() { return key; } public boolean isLive(long currentTimeMillis) { return currentTimeMillis < timelife; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Key other = (Key) obj; if (this.key != other.key && (this.key == null || !this.key.equals(other.key))) { return false; } return true; } @Override public int hashCode() { int hash = 7; hash = 43 * hash + (this.key != null ? this.key.hashCode() : 0); return hash; } @Override public String toString() { return "Key{" + "key=" + key + '}'; } } }
      
      






All Articles