View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.common.lru;
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Iterator;
25  import java.util.List;
26  
27  /**
28   * Threadsafe synchronized implementation of LruCache based on LinkedHashMap.
29   * Threadsafety is provided by
30   * method synchronization.
31   * <p>
32   * This cache implementation should be used with low number of threads.
33   *
34   * @author Damian Momot
35   */
36  public class SynchronizedLruCache<K, V> extends AbstractLruCache<K, V> {
37    private static final int DEFAULT_INITIAL_CAPACITY = 16;
38  
39    private static final float DEFAULT_LOAD_FACTOR = 0.75f;
40  
41    private final CapacityLruLinkedHashMap<K, InterfaceLruCacheEntry<V>> cacheMap;
42  
43    /**
44     * Creates new SynchronizedLruCache
45     *
46     * @param capacity max cache capacity
47     * @param ttl time to live in milliseconds
48     * @param initialCapacity initial cache capacity
49     * @param loadFactor
50     */
51    public SynchronizedLruCache(final int capacity, final long ttl,
52                                final int initialCapacity,
53                                final float loadFactor) {
54      super(ttl);
55      cacheMap =
56          new CapacityLruLinkedHashMap<K, InterfaceLruCacheEntry<V>>(capacity,
57                                                                     initialCapacity,
58                                                                     loadFactor);
59    }
60  
61    /**
62     * Creates new SynchronizedLruCache with DEFAULT_LOAD_FACTOR
63     *
64     * @param capacity max cache capacity
65     * @param ttl time to live in milliseconds
66     * @param initialCapacity initial cache capacity
67     */
68    public SynchronizedLruCache(final int capacity, final long ttl,
69                                final int initialCapacity) {
70      this(capacity, ttl, initialCapacity, DEFAULT_LOAD_FACTOR);
71    }
72  
73    /**
74     * Creates new SynchronizedLruCache with DEFAULT_LOAD_FACTOR and
75     * DEFAULT_INITIAL_CAPACITY
76     *
77     * @param capacity max cache capacity
78     * @param ttl time to live in milliseconds
79     */
80    public SynchronizedLruCache(final int capacity, final long ttl) {
81      this(capacity, ttl, DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
82    }
83  
84    @Override
85    public synchronized void clear() {
86      cacheMap.clear();
87    }
88  
89    @Override
90    public synchronized V get(final K key) {
91      return super.get(key);
92    }
93  
94    @Override
95    public final int getCapacity() {
96      return cacheMap.getCapacity();
97    }
98  
99    @Override
100   protected final InterfaceLruCacheEntry<V> getEntry(final K key) {
101     return cacheMap.get(key);
102   }
103 
104   @Override
105   public synchronized int size() {
106     return cacheMap.size();
107   }
108 
109   @Override
110   public synchronized void put(final K key, final V value, final long ttl) {
111     super.put(key, value, ttl);
112   }
113 
114   @Override
115   protected final void putEntry(final K key,
116                                 final InterfaceLruCacheEntry<V> entry) {
117     cacheMap.put(key, entry);
118   }
119 
120   @Override
121   public synchronized V remove(final K key) {
122     final InterfaceLruCacheEntry<V> cv = cacheMap.remove(key);
123     if (cv != null) {
124       return cv.getValue();
125     }
126     return null;
127   }
128 
129   @Override
130   public final Collection<V> values() {
131     final Collection<InterfaceLruCacheEntry<V>> cacheEntry = cacheMap.values();
132     final List<V> list = new ArrayList<V>(cacheEntry.size());
133     for (final InterfaceLruCacheEntry<V> entry : cacheEntry) {
134       list.add(entry.getValue());
135     }
136     return list;
137   }
138 
139   @Override
140   public synchronized int forceClearOldest() {
141     final long timeRef = System.currentTimeMillis();
142     final Collection<InterfaceLruCacheEntry<V>> collection = cacheMap.values();
143     final Iterator<InterfaceLruCacheEntry<V>> iterator = collection.iterator();
144     int nb = 0;
145     while (iterator.hasNext()) {
146       final InterfaceLruCacheEntry<V> v = iterator.next();
147       if (!v.isStillValid(timeRef)) {
148         iterator.remove();
149         nb++;
150       }
151     }
152     return nb;
153   }
154 
155 }