рдЗрддрдирд╛ рд╕рдордп рдкрд╣рд▓реЗ рдирд╣реАрдВ, рдореБрдЭреЗ рдПрдХ рдХреИрд╢ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдХрд╛рдо рдерд╛ рдЬреЛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдордп рдмреАрддрдиреЗ рдХреЗ рдмрд╛рдж рдЦреБрдж рдХреЛ рд╕рд╛рдл рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдереАрдВ:
- рд╣рд▓реНрдХреЗ рд╡рдЬрди
- рдзрд╛рдЧрд╛ рд╕реБрд░рдХреНрд╖рд╛
рдмрд╕ рдЗрддрдирд╛ рд╣реАред Java.util.concurrent рдХреЗ рд╕рд╛рде рдЗрд╕ рдХрд╛рд░реНрдп рдХреЛ рд▓рд┐рдЦрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╕реМрджрд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ред рдЗрд╕ рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдЪрд╛рд░ рдореЗрд░реЗ рдПрдХ рд╕рд╣рдХрд░реНрдореА рджреНрд╡рд╛рд░рд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЬрд┐рд╕рдХреЗ рдкрд╛рд╕ рдХреБрдЫ рд╕рдорд╛рди рдерд╛, рд▓реЗрдХрд┐рди рдЙрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╕реЗ рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддрд╛ рдерд╛ рдЬрд┐рд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереАред рддреЛ, рдЪрд▓рд┐рдП рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ:
рдХреБрдВрдЬреА рдПрдХ рдЖрдВрддрд░рд┐рдХ рд╡рд░реНрдЧ рд╣реЛрдЧреА, рдЬреЛ рдЕрдкрдиреЗ рдкреНрд░рддреНрдпрдХреНрд╖ рдЙрджреНрджреЗрд╢реНрдп рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░реЗрдЧреА рдХрд┐ рдХреНрдпрд╛ рдпрд╣ "рд▓рд╛рдЗрд╡" рд╣реИ рдпрд╛ рдЗрд╕реЗ рдХреИрд╢ рд╕реЗ рд╣рдЯрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХрд╛ рдЕрд╕реНрддрд┐рддреНрд╡ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдпрд╛ рд╣реИ:
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; } }); }
рд╣рдо рдзрд╛рдЧреЗ рдХреЛ рдПрдХ рджрд╛рдирд╡ рдмрдирд╛ рджреЗрдВрдЧреЗ, рддрд╛рдХрд┐ рдЬрдм рдореБрдЦреНрдп рдзрд╛рдЧрд╛ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рдП, рддреЛ рдХреИрд╢ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рд╡рд╛рд▓реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рднреА рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рдПрдЧреАред
рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ, рд╣рдорд╛рд░реЗ рд╢реЗрдбреНрдпреВрд▓рд░ рдХреЛ рдЪрд▓рд╛рдПрдВ, рдЬреЛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдордп рдХреЗ рдмрд╛рдж (рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╕реНрдЯреЛрд░реЗрдЬ рдЯрд╛рдЗрдо рдХрд╛ рдкрд╛рдВрдЪрд╡рд╛рдВ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред) рдореИрдк рдкрд░ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдЙрди рд╕рднреА рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЛ рдбрд┐рд▓реАрдЯ рдХрд░ рджреЗрдЧрд╛, рдЬрд┐рдирдХрд╛ рдЬреАрд╡рдирдХрд╛рд▓ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЪреБрдХрд╛ рд╣реИ:
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; } }); 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); } 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; } public void put(K key, V data) { globalMap.put(new Key(key, default_timeout), data); } public void put(K key, V data, long timeout) { globalMap.put(new Key(key, timeout), data); } public V get(K key) { return globalMap.get(new Key(key)); } public void remove(K key) { globalMap.remove(new Key(key)); } public void removeAll() { globalMap.clear(); } 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; } 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 + '}'; } } }