From 4e815f5a439b164219a2bf1e7f510d6b5c7eef65 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 19 Apr 2017 14:03:46 +0300 Subject: [PATCH 01/12] SoftCache task --- SoftCache/.idea/misc.xml | 6 + SoftCache/.idea/modules.xml | 8 + SoftCache/.idea/workspace.xml | 598 ++++++++++++++++++ SoftCache/SoftCache.iml | 11 + .../out/production/SoftCache/Cache.class | Bin 0 -> 380 bytes .../production/SoftCache/SoftCacheMap.class | Bin 0 -> 1722 bytes SoftCache/src/Cache.java | 24 + SoftCache/src/SoftCacheMap.java | 45 ++ 8 files changed, 692 insertions(+) create mode 100644 SoftCache/.idea/misc.xml create mode 100644 SoftCache/.idea/modules.xml create mode 100644 SoftCache/.idea/workspace.xml create mode 100644 SoftCache/SoftCache.iml create mode 100644 SoftCache/out/production/SoftCache/Cache.class create mode 100644 SoftCache/out/production/SoftCache/SoftCacheMap.class create mode 100644 SoftCache/src/Cache.java create mode 100644 SoftCache/src/SoftCacheMap.java diff --git a/SoftCache/.idea/misc.xml b/SoftCache/.idea/misc.xml new file mode 100644 index 0000000..0548357 --- /dev/null +++ b/SoftCache/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SoftCache/.idea/modules.xml b/SoftCache/.idea/modules.xml new file mode 100644 index 0000000..d370c02 --- /dev/null +++ b/SoftCache/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/SoftCache/.idea/workspace.xml b/SoftCache/.idea/workspace.xml new file mode 100644 index 0000000..70f81df --- /dev/null +++ b/SoftCache/.idea/workspace.xml @@ -0,0 +1,598 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1492599433704 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SoftCache/SoftCache.iml b/SoftCache/SoftCache.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/SoftCache/SoftCache.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/SoftCache/out/production/SoftCache/Cache.class b/SoftCache/out/production/SoftCache/Cache.class new file mode 100644 index 0000000000000000000000000000000000000000..4b0ec5d7c361422a7ac15e256a5bad35f230d45d GIT binary patch literal 380 zcmZvY!H&UD6o&spwR9Mrc?jAK8!Hu?NhCr-Lb|`2qe!RZYCW8V2bhPNIIYA&?e2H( z`M-0|{rkV(01WVL!Ljf~Xhxh)w@b}uPEtb0ogdUi^<$Mp{l(_MVd{J35}~o$M~O-^ z&4jwUp84K7@CnsZCYJ6SOIhLtqRFF@%+IFg-{VDmwJ>I-Mds$^(P%a-hl4k@ak-6P zua21xd9shiZ2zcm$Gv<-8B+kkdEM9~5GwLdfMLipUbmL!K#863f35ux^`TDs~s_1FYjw7TCrstjp7?O zSYn7(jGC$0EsHbk`ZHGCP(w3o#Vyn3HExxpkj1OTO0#NziE*%OnEYMqaF1Kt+FpYq>2g!o8atY0h-WVtvg^h%!$4VZ zZEAX*lOh6DYuw(dez5p4H*JQQtW;X3+F2>)RYXM`@Go6QE{S7ERBTN@AOep(c+?{7 zY(H#2w9pnl(HbpBietC~-(`+i{IGdKZ^L?nYZk+_4E%m?pX+u>uGtIyqt1&;1$2&5 z0c-wn*>O$oPRAc9x7#p=c%|90bpF~9JxR&7&k0c~ZsHcb@J*D8A!JmnBgZh(lkb}o zk+Q*%?4`Km0(eu!Bwnh>BBx@u$0PSiyd4vHQz}L=Mx!9tcnR1wh75Nspx)EaFbrk; znw;s^4YG8(Ph4`YW4=Fx`}9GkLBmGBfN+QI!}Pfaa05}=laaLErpN|@v;&g4GqBt_ z0=s7jen;r5lRZM~0A+|Zgh9GexI<5>dj@xLkDi!t!^7JrjsV4`a^Dcjw-LTTqz&a4 zGM57vh@P@jN(`b$k|FqEOi+1(WY`7rNC=W-jT6m;bBaySmRjNQZX@i}nRaN-5!o%A zA=XCxQ%{Nb;{w5@sA@ql=AP&hq&)(Vchi`mZ2APRuI!pCwXd>qBAuklr?0AvM$l8X zNO#eps8H61`mdfm6cnVcL|r|}bur5x#yn{e+GDx=1rlux2 { + /** + * Возвращает соответствующее значение, если оно ещё в кэше, иначе null + */ + V getIfPresent(K key); + + /** + * Сохраняет value по соответствующему ключу key + */ + void put(K key, V value); + + /** + * Удаляет соответствующее ключу key значение + */ + V remove(K key); + + /** + * Очищает кэш + */ + void clear(); +} diff --git a/SoftCache/src/SoftCacheMap.java b/SoftCache/src/SoftCacheMap.java new file mode 100644 index 0000000..43e4fa2 --- /dev/null +++ b/SoftCache/src/SoftCacheMap.java @@ -0,0 +1,45 @@ +//import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.util.HashMap; + +/** + * Created by david on 18.04.17. + */ + +public class SoftCacheMap implements Cache { + + private HashMap> hashMap; + //private ReferenceQueue> referenceQueue; + + public SoftCacheMap() { + this.hashMap = new HashMap>(); + // this.referenceQueue = new ReferenceQueue>(); + } + + @Override + public String getIfPresent(Integer key) { + if (hashMap.get(key).get() != null) { + return hashMap.get(key).get(); + } + return null; + } + + @Override + public void put(Integer key, String value) { + hashMap.put(key, new SoftReference(value)); + } + + @Override + public String remove(Integer key) { + if (hashMap.get(key).get() != null) { + + return hashMap.remove(key).get(); + } + return null; + } + + @Override + public void clear() { + hashMap.clear(); + } +} \ No newline at end of file From b5a6e3b71ffad80aeea17b96a2ce31ce742939c6 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 23 Apr 2017 00:11:31 +0300 Subject: [PATCH 02/12] Binary files deleted --- SoftCache/out/production/SoftCache/Cache.class | Bin 380 -> 0 bytes .../out/production/SoftCache/SoftCacheMap.class | Bin 1722 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 SoftCache/out/production/SoftCache/Cache.class delete mode 100644 SoftCache/out/production/SoftCache/SoftCacheMap.class diff --git a/SoftCache/out/production/SoftCache/Cache.class b/SoftCache/out/production/SoftCache/Cache.class deleted file mode 100644 index 4b0ec5d7c361422a7ac15e256a5bad35f230d45d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 380 zcmZvY!H&UD6o&spwR9Mrc?jAK8!Hu?NhCr-Lb|`2qe!RZYCW8V2bhPNIIYA&?e2H( z`M-0|{rkV(01WVL!Ljf~Xhxh)w@b}uPEtb0ogdUi^<$Mp{l(_MVd{J35}~o$M~O-^ z&4jwUp84K7@CnsZCYJ6SOIhLtqRFF@%+IFg-{VDmwJ>I-Mds$^(P%a-hl4k@ak-6P zua21xd9shiZ2zcm$Gv<-8B+kkdEM9~5GwLdfMLipUbmL!K#863f35ux^`TDs~s_1FYjw7TCrstjp7?O zSYn7(jGC$0EsHbk`ZHGCP(w3o#Vyn3HExxpkj1OTO0#NziE*%OnEYMqaF1Kt+FpYq>2g!o8atY0h-WVtvg^h%!$4VZ zZEAX*lOh6DYuw(dez5p4H*JQQtW;X3+F2>)RYXM`@Go6QE{S7ERBTN@AOep(c+?{7 zY(H#2w9pnl(HbpBietC~-(`+i{IGdKZ^L?nYZk+_4E%m?pX+u>uGtIyqt1&;1$2&5 z0c-wn*>O$oPRAc9x7#p=c%|90bpF~9JxR&7&k0c~ZsHcb@J*D8A!JmnBgZh(lkb}o zk+Q*%?4`Km0(eu!Bwnh>BBx@u$0PSiyd4vHQz}L=Mx!9tcnR1wh75Nspx)EaFbrk; znw;s^4YG8(Ph4`YW4=Fx`}9GkLBmGBfN+QI!}Pfaa05}=laaLErpN|@v;&g4GqBt_ z0=s7jen;r5lRZM~0A+|Zgh9GexI<5>dj@xLkDi!t!^7JrjsV4`a^Dcjw-LTTqz&a4 zGM57vh@P@jN(`b$k|FqEOi+1(WY`7rNC=W-jT6m;bBaySmRjNQZX@i}nRaN-5!o%A zA=XCxQ%{Nb;{w5@sA@ql=AP&hq&)(Vchi`mZ2APRuI!pCwXd>qBAuklr?0AvM$l8X zNO#eps8H61`mdfm6cnVcL|r|}bur5x#yn{e+GDx=1rlux2 Date: Sun, 23 Apr 2017 18:04:06 +0300 Subject: [PATCH 03/12] ReferenceQueue checking added --- SoftCache/.idea/workspace.xml | 137 ++++++++++++++++++++++---------- SoftCache/src/SoftCacheMap.java | 57 +++++++++---- 2 files changed, 135 insertions(+), 59 deletions(-) diff --git a/SoftCache/.idea/workspace.xml b/SoftCache/.idea/workspace.xml index 70f81df..f447b3c 100644 --- a/SoftCache/.idea/workspace.xml +++ b/SoftCache/.idea/workspace.xml @@ -15,7 +15,7 @@ - + @@ -29,14 +29,10 @@ - - + + - - - - @@ -92,6 +88,8 @@ + + @@ -121,16 +119,30 @@ - - + - + + + + @@ -489,6 +502,12 @@ + project + + + + + @@ -504,6 +523,14 @@ + + + + + + + + - + + + + + + + + - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - + + + + - - + @@ -564,7 +601,9 @@ - + + @@ -582,14 +621,28 @@ - - + + + + + + + + + + + + + + + + + + + + - - - - diff --git a/SoftCache/src/SoftCacheMap.java b/SoftCache/src/SoftCacheMap.java index 43e4fa2..65c8782 100644 --- a/SoftCache/src/SoftCacheMap.java +++ b/SoftCache/src/SoftCacheMap.java @@ -1,45 +1,68 @@ -//import java.lang.ref.ReferenceQueue; +import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.HashMap; - -/** - * Created by david on 18.04.17. - */ +import java.util.HashSet; public class SoftCacheMap implements Cache { - private HashMap> hashMap; - //private ReferenceQueue> referenceQueue; + private HashMap> hashMap1; + private HashMap, HashSet> hashMap2; + private ReferenceQueue> referenceQueue; + + private SoftCacheMap() { + hashMap1 = new HashMap(); + hashMap2 = new HashMap(); + referenceQueue = new ReferenceQueue(); + } - public SoftCacheMap() { - this.hashMap = new HashMap>(); - // this.referenceQueue = new ReferenceQueue>(); + private boolean delete() { + SoftReference reference = (SoftReference) referenceQueue.poll(); + if (reference != null) { + if (hashMap1.entrySet().contains(reference)) { + HashSet localSet = hashMap2.remove(reference); + for (Object local : localSet) { + hashMap1.remove(local); + } + } + return true; + } else { + return false; + } } @Override public String getIfPresent(Integer key) { - if (hashMap.get(key).get() != null) { - return hashMap.get(key).get(); + if (hashMap1.get(key).get() != null) { + return hashMap1.get(key).get(); } return null; } @Override public void put(Integer key, String value) { - hashMap.put(key, new SoftReference(value)); + hashMap1.put(key, new SoftReference(value, referenceQueue)); + if (hashMap2.get(hashMap1.get(key)) != null) { + hashMap2.get(hashMap1.get(key)).add(key); + } else { + hashMap2.put(hashMap1.get(key), new HashSet(key)); + } + while (delete()) { + //delete references + } } @Override public String remove(Integer key) { - if (hashMap.get(key).get() != null) { - - return hashMap.remove(key).get(); + if (hashMap1.get(key).get() != null) { + hashMap2.remove(hashMap1.get(key)); + return hashMap1.remove(key).get(); } return null; } @Override public void clear() { - hashMap.clear(); + hashMap1.clear(); + hashMap2.clear(); } } \ No newline at end of file From 694ea72670d22d65340a036276de68acc33dc11f Mon Sep 17 00:00:00 2001 From: David Date: Mon, 24 Apr 2017 14:28:02 +0300 Subject: [PATCH 04/12] Fixes --- SoftCache/.idea/workspace.xml | 43 +++++++++++++------ SoftCache/SoftCache.iml | 9 +--- SoftCache/src/SoftCacheMap.java | 75 ++++++++++++++++++--------------- 3 files changed, 74 insertions(+), 53 deletions(-) diff --git a/SoftCache/.idea/workspace.xml b/SoftCache/.idea/workspace.xml index f447b3c..a9cfb23 100644 --- a/SoftCache/.idea/workspace.xml +++ b/SoftCache/.idea/workspace.xml @@ -19,8 +19,8 @@ - - + + @@ -30,7 +30,7 @@ - + @@ -88,8 +88,6 @@ - - @@ -118,6 +116,8 @@ + + @@ -543,12 +543,13 @@ - @@ -566,7 +567,6 @@ - @@ -578,9 +578,8 @@ - + - @@ -591,7 +590,9 @@ + + @@ -602,7 +603,7 @@ - @@ -637,10 +638,28 @@ + + + + + + + + + + + + + + + + + + - + diff --git a/SoftCache/SoftCache.iml b/SoftCache/SoftCache.iml index c90834f..19dbd15 100644 --- a/SoftCache/SoftCache.iml +++ b/SoftCache/SoftCache.iml @@ -1,11 +1,6 @@ - - - - - - - + + \ No newline at end of file diff --git a/SoftCache/src/SoftCacheMap.java b/SoftCache/src/SoftCacheMap.java index 65c8782..0d99f9e 100644 --- a/SoftCache/src/SoftCacheMap.java +++ b/SoftCache/src/SoftCacheMap.java @@ -3,66 +3,73 @@ import java.util.HashMap; import java.util.HashSet; -public class SoftCacheMap implements Cache { +public class SoftCacheMap implements Cache { - private HashMap> hashMap1; - private HashMap, HashSet> hashMap2; - private ReferenceQueue> referenceQueue; + private HashMap> cache; + private HashMap, HashSet> subsidiaryMap; + private ReferenceQueue> referenceQueue; private SoftCacheMap() { - hashMap1 = new HashMap(); - hashMap2 = new HashMap(); - referenceQueue = new ReferenceQueue(); + cache = new HashMap<>(); + /** + * второй hashMap - вспомогательный, используется при удалении из кэша + * тех ссылок, которые попали в referenceQueue. Чтобы не искать все ключи, + * соответствующие одной ссылке, храню Set из таких ключей в качестве значения + * во втором hashMap-e. + */ + subsidiaryMap = new HashMap<>(); + referenceQueue = new ReferenceQueue<>(); } - private boolean delete() { - SoftReference reference = (SoftReference) referenceQueue.poll(); - if (reference != null) { - if (hashMap1.entrySet().contains(reference)) { - HashSet localSet = hashMap2.remove(reference); - for (Object local : localSet) { - hashMap1.remove(local); + private void clean() { + boolean done = false; + while (!done) { + SoftReference reference = (SoftReference) referenceQueue.poll(); + if (reference != null) { + if (cache.entrySet().contains(reference)) { + HashSet localSet = subsidiaryMap.remove(reference); + for (Integer local : localSet) { + cache.remove(local); + } } + } else { + done = true; } - return true; - } else { - return false; } } @Override - public String getIfPresent(Integer key) { - if (hashMap1.get(key).get() != null) { - return hashMap1.get(key).get(); + public Object getIfPresent(Integer key) { + if (cache.containsKey(key)) { + return cache.get(key).get(); } return null; } @Override - public void put(Integer key, String value) { - hashMap1.put(key, new SoftReference(value, referenceQueue)); - if (hashMap2.get(hashMap1.get(key)) != null) { - hashMap2.get(hashMap1.get(key)).add(key); + public void put(Integer key, Object value) { + SoftReference reference = new SoftReference(value, referenceQueue); + cache.put(key, reference); + if (subsidiaryMap.containsKey(reference)) { + subsidiaryMap.get(reference).add(key); } else { - hashMap2.put(hashMap1.get(key), new HashSet(key)); - } - while (delete()) { - //delete references + subsidiaryMap.put(reference, new HashSet<>(key)); } + clean(); } @Override - public String remove(Integer key) { - if (hashMap1.get(key).get() != null) { - hashMap2.remove(hashMap1.get(key)); - return hashMap1.remove(key).get(); + public Object remove(Integer key) { + if ((cache.containsKey(key)) && (cache.get(key).get() != null)) { + subsidiaryMap.remove(cache.get(key)); + return cache.remove(key).get(); } return null; } @Override public void clear() { - hashMap1.clear(); - hashMap2.clear(); + cache.clear(); + subsidiaryMap.clear(); } } \ No newline at end of file From 01f750bf480a79e43c17e5c2c8c7e44b08877149 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 24 Apr 2017 16:10:09 +0300 Subject: [PATCH 05/12] Delete unnecessary files --- .gitignore | 2 + SoftCache/.idea/misc.xml | 6 - SoftCache/.idea/modules.xml | 8 - SoftCache/.idea/workspace.xml | 670 ---------------------------------- SoftCache/SoftCache.iml | 6 - 5 files changed, 2 insertions(+), 690 deletions(-) create mode 100644 .gitignore delete mode 100644 SoftCache/.idea/misc.xml delete mode 100644 SoftCache/.idea/modules.xml delete mode 100644 SoftCache/.idea/workspace.xml delete mode 100644 SoftCache/SoftCache.iml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8cf4617 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.iml +*.xml diff --git a/SoftCache/.idea/misc.xml b/SoftCache/.idea/misc.xml deleted file mode 100644 index 0548357..0000000 --- a/SoftCache/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/SoftCache/.idea/modules.xml b/SoftCache/.idea/modules.xml deleted file mode 100644 index d370c02..0000000 --- a/SoftCache/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/SoftCache/.idea/workspace.xml b/SoftCache/.idea/workspace.xml deleted file mode 100644 index a9cfb23..0000000 --- a/SoftCache/.idea/workspace.xml +++ /dev/null @@ -1,670 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - DEFINITION_ORDER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - project - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1492599433704 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/SoftCache/SoftCache.iml b/SoftCache/SoftCache.iml deleted file mode 100644 index 19dbd15..0000000 --- a/SoftCache/SoftCache.iml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 47cd948bb15fd88817bc0a278ba1a34bd985ef6a Mon Sep 17 00:00:00 2001 From: David Date: Mon, 24 Apr 2017 16:48:11 +0300 Subject: [PATCH 06/12] Queue of recently used objects added --- SoftCache/src/SoftCacheMap.java | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/SoftCache/src/SoftCacheMap.java b/SoftCache/src/SoftCacheMap.java index 0d99f9e..209e620 100644 --- a/SoftCache/src/SoftCacheMap.java +++ b/SoftCache/src/SoftCacheMap.java @@ -1,15 +1,16 @@ import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; -import java.util.HashMap; -import java.util.HashSet; +import java.util.*; public class SoftCacheMap implements Cache { private HashMap> cache; private HashMap, HashSet> subsidiaryMap; private ReferenceQueue> referenceQueue; + private Deque recentlyUsed; + private int maxSize; - private SoftCacheMap() { + private SoftCacheMap(int size) { cache = new HashMap<>(); /** * второй hashMap - вспомогательный, используется при удалении из кэша @@ -19,8 +20,23 @@ private SoftCacheMap() { */ subsidiaryMap = new HashMap<>(); referenceQueue = new ReferenceQueue<>(); + recentlyUsed = new LinkedList<>(); + maxSize = size; } + private void putInQueue(Object object) { + if (object != null) { + recentlyUsed.remove(object); + if (recentlyUsed.size() < maxSize) { + recentlyUsed.addLast(object); + } else { + recentlyUsed.addLast(object); + recentlyUsed.removeFirst(); + } + } + } + + private void clean() { boolean done = false; while (!done) { @@ -41,6 +57,7 @@ private void clean() { @Override public Object getIfPresent(Integer key) { if (cache.containsKey(key)) { + putInQueue(cache.get(key).get()); return cache.get(key).get(); } return null; @@ -50,6 +67,7 @@ public Object getIfPresent(Integer key) { public void put(Integer key, Object value) { SoftReference reference = new SoftReference(value, referenceQueue); cache.put(key, reference); + putInQueue(value); if (subsidiaryMap.containsKey(reference)) { subsidiaryMap.get(reference).add(key); } else { From b63aea27d1f2ef329575d97ddd8926386fd5df55 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 25 Apr 2017 00:35:56 +0300 Subject: [PATCH 07/12] Fixes --- SoftCache/src/SoftCacheMap.java | 59 ++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/SoftCache/src/SoftCacheMap.java b/SoftCache/src/SoftCacheMap.java index 209e620..da9fd9f 100644 --- a/SoftCache/src/SoftCacheMap.java +++ b/SoftCache/src/SoftCacheMap.java @@ -2,12 +2,12 @@ import java.lang.ref.SoftReference; import java.util.*; -public class SoftCacheMap implements Cache { +public class SoftCacheMap implements Cache { - private HashMap> cache; - private HashMap, HashSet> subsidiaryMap; - private ReferenceQueue> referenceQueue; - private Deque recentlyUsed; + private HashMap> cache; + private HashMap, HashSet> subsidiaryMap; + private ReferenceQueue referenceQueue; + private Deque recentlyUsed; private int maxSize; private SoftCacheMap(int size) { @@ -24,14 +24,16 @@ private SoftCacheMap(int size) { maxSize = size; } - private void putInQueue(Object object) { - if (object != null) { - recentlyUsed.remove(object); - if (recentlyUsed.size() < maxSize) { - recentlyUsed.addLast(object); - } else { - recentlyUsed.addLast(object); - recentlyUsed.removeFirst(); + private void putInQueue(V object) { + if (maxSize > 0) { + if (object != null) { + recentlyUsed.remove(object); + if (recentlyUsed.size() < maxSize) { + recentlyUsed.addLast(object); + } else { + recentlyUsed.addLast(object); + recentlyUsed.removeFirst(); + } } } } @@ -42,7 +44,7 @@ private void clean() { while (!done) { SoftReference reference = (SoftReference) referenceQueue.poll(); if (reference != null) { - if (cache.entrySet().contains(reference)) { + if (subsidiaryMap.containsKey(reference)) { HashSet localSet = subsidiaryMap.remove(reference); for (Integer local : localSet) { cache.remove(local); @@ -55,7 +57,7 @@ private void clean() { } @Override - public Object getIfPresent(Integer key) { + public V getIfPresent(Integer key) { if (cache.containsKey(key)) { putInQueue(cache.get(key).get()); return cache.get(key).get(); @@ -64,20 +66,21 @@ public Object getIfPresent(Integer key) { } @Override - public void put(Integer key, Object value) { - SoftReference reference = new SoftReference(value, referenceQueue); + public void put(Integer key, V value) { + SoftReference reference = new SoftReference(value, referenceQueue); cache.put(key, reference); putInQueue(value); if (subsidiaryMap.containsKey(reference)) { subsidiaryMap.get(reference).add(key); } else { - subsidiaryMap.put(reference, new HashSet<>(key)); + subsidiaryMap.put(reference, new HashSet<>()); + subsidiaryMap.get(reference).add(key); } clean(); } @Override - public Object remove(Integer key) { + public V remove(Integer key) { if ((cache.containsKey(key)) && (cache.get(key).get() != null)) { subsidiaryMap.remove(cache.get(key)); return cache.remove(key).get(); @@ -90,4 +93,22 @@ public void clear() { cache.clear(); subsidiaryMap.clear(); } + + public static void main(String... args) { + SoftCacheMap cache = new SoftCacheMap(2); + for (int i = 0; i < 100; ++i) { + cache.put(i, i); + } + for (int i = 0; i < 100; ++i) { + if (cache.getIfPresent(i) == null) { + System.out.println("it doesn't work"); + } + } + System.gc(); + for (int i = 99; i >= 0; --i) { + if (cache.getIfPresent(i) == null) { + System.out.println("it works"); + } + } + } } \ No newline at end of file From 0f58e757e83475990eef2f6f32fe9432e0f2c603 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 25 Apr 2017 17:47:02 +0300 Subject: [PATCH 08/12] Small fixes + test added --- SoftCache/src/SoftCacheMap.java | 82 +++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 19 deletions(-) diff --git a/SoftCache/src/SoftCacheMap.java b/SoftCache/src/SoftCacheMap.java index da9fd9f..4956121 100644 --- a/SoftCache/src/SoftCacheMap.java +++ b/SoftCache/src/SoftCacheMap.java @@ -1,16 +1,19 @@ import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.*; +import java.util.concurrent.TimeUnit; public class SoftCacheMap implements Cache { private HashMap> cache; private HashMap, HashSet> subsidiaryMap; - private ReferenceQueue referenceQueue; + private ReferenceQueue referenceQueue; private Deque recentlyUsed; private int maxSize; + private int cleaningFrequency; + private int numOfPuts; - private SoftCacheMap(int size) { + private SoftCacheMap(int size, int frequency) { cache = new HashMap<>(); /** * второй hashMap - вспомогательный, используется при удалении из кэша @@ -19,9 +22,11 @@ private SoftCacheMap(int size) { * во втором hashMap-e. */ subsidiaryMap = new HashMap<>(); - referenceQueue = new ReferenceQueue<>(); + referenceQueue = new ReferenceQueue(); recentlyUsed = new LinkedList<>(); maxSize = size; + cleaningFrequency = frequency; + numOfPuts = 0; } private void putInQueue(V object) { @@ -47,7 +52,9 @@ private void clean() { if (subsidiaryMap.containsKey(reference)) { HashSet localSet = subsidiaryMap.remove(reference); for (Integer local : localSet) { - cache.remove(local); + if (reference.get() == null) { + cache.remove(local); + } } } } else { @@ -67,6 +74,7 @@ public V getIfPresent(Integer key) { @Override public void put(Integer key, V value) { + ++numOfPuts; SoftReference reference = new SoftReference(value, referenceQueue); cache.put(key, reference); putInQueue(value); @@ -76,7 +84,9 @@ public void put(Integer key, V value) { subsidiaryMap.put(reference, new HashSet<>()); subsidiaryMap.get(reference).add(key); } - clean(); + if (numOfPuts % cleaningFrequency == 0) { + clean(); + } } @Override @@ -94,21 +104,55 @@ public void clear() { subsidiaryMap.clear(); } - public static void main(String... args) { - SoftCacheMap cache = new SoftCacheMap(2); - for (int i = 0; i < 100; ++i) { - cache.put(i, i); - } - for (int i = 0; i < 100; ++i) { - if (cache.getIfPresent(i) == null) { - System.out.println("it doesn't work"); - } + public static void main(String... args) throws InterruptedException { + + /** + * проверка корректной работы referenceQueue + */ + + SoftCacheMap cache1 = new SoftCacheMap(0, 1); + cache1.put(0, new Integer(0)); + + /** + * должен быть 0 + */ + System.out.println(cache1.getIfPresent(0)); + + try { + Object[] big = new Object[(int) Runtime.getRuntime().maxMemory()]; + } catch (OutOfMemoryError e) { + // ignore } - System.gc(); - for (int i = 99; i >= 0; --i) { - if (cache.getIfPresent(i) == null) { - System.out.println("it works"); - } + + /** + * должен быть null + */ + System.out.println(cache1.getIfPresent(0)); + cache1.clear(); + + + /** + * проверка корректной работы recentlyUsed + */ + + SoftCacheMap cache2 = new SoftCacheMap(1, 1); + cache2.put(0, new Integer(0)); + + /** + * должен быть 0 + */ + System.out.println(cache2.getIfPresent(0)); + + try { + Object[] big = new Object[(int) Runtime.getRuntime().maxMemory()]; + } catch (OutOfMemoryError e) { + // ignore } + + /** + * должен быть 0 + */ + System.out.println(cache2.getIfPresent(0)); + cache2.clear(); } } \ No newline at end of file From 031dec16be935722aef11b0832120972c7421c25 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 25 Apr 2017 18:04:33 +0300 Subject: [PATCH 09/12] Small fixes --- SoftCache/src/SoftCacheMap.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SoftCache/src/SoftCacheMap.java b/SoftCache/src/SoftCacheMap.java index 4956121..61ea83d 100644 --- a/SoftCache/src/SoftCacheMap.java +++ b/SoftCache/src/SoftCacheMap.java @@ -1,7 +1,9 @@ import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; -import java.util.*; -import java.util.concurrent.TimeUnit; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; public class SoftCacheMap implements Cache { @@ -22,7 +24,7 @@ private SoftCacheMap(int size, int frequency) { * во втором hashMap-e. */ subsidiaryMap = new HashMap<>(); - referenceQueue = new ReferenceQueue(); + referenceQueue = new ReferenceQueue<>(); recentlyUsed = new LinkedList<>(); maxSize = size; cleaningFrequency = frequency; @@ -75,7 +77,7 @@ public V getIfPresent(Integer key) { @Override public void put(Integer key, V value) { ++numOfPuts; - SoftReference reference = new SoftReference(value, referenceQueue); + SoftReference reference = new SoftReference<>(value, referenceQueue); cache.put(key, reference); putInQueue(value); if (subsidiaryMap.containsKey(reference)) { From 0da56dd954dc83d1f1d177a5d4037a9d5a851157 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 25 Apr 2017 20:45:02 +0300 Subject: [PATCH 10/12] Fixes --- SoftCache/src/SoftCacheMap.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/SoftCache/src/SoftCacheMap.java b/SoftCache/src/SoftCacheMap.java index 61ea83d..0fee49a 100644 --- a/SoftCache/src/SoftCacheMap.java +++ b/SoftCache/src/SoftCacheMap.java @@ -5,10 +5,10 @@ import java.util.HashSet; import java.util.LinkedList; -public class SoftCacheMap implements Cache { +public class SoftCacheMap implements Cache { - private HashMap> cache; - private HashMap, HashSet> subsidiaryMap; + private HashMap> cache; + private HashMap, HashSet> subsidiaryMap; private ReferenceQueue referenceQueue; private Deque recentlyUsed; private int maxSize; @@ -52,8 +52,8 @@ private void clean() { SoftReference reference = (SoftReference) referenceQueue.poll(); if (reference != null) { if (subsidiaryMap.containsKey(reference)) { - HashSet localSet = subsidiaryMap.remove(reference); - for (Integer local : localSet) { + HashSet localSet = subsidiaryMap.remove(reference); + for (K local : localSet) { if (reference.get() == null) { cache.remove(local); } @@ -66,7 +66,7 @@ private void clean() { } @Override - public V getIfPresent(Integer key) { + public V getIfPresent(K key) { if (cache.containsKey(key)) { putInQueue(cache.get(key).get()); return cache.get(key).get(); @@ -75,7 +75,7 @@ public V getIfPresent(Integer key) { } @Override - public void put(Integer key, V value) { + public void put(K key, V value) { ++numOfPuts; SoftReference reference = new SoftReference<>(value, referenceQueue); cache.put(key, reference); @@ -92,7 +92,7 @@ public void put(Integer key, V value) { } @Override - public V remove(Integer key) { + public V remove(K key) { if ((cache.containsKey(key)) && (cache.get(key).get() != null)) { subsidiaryMap.remove(cache.get(key)); return cache.remove(key).get(); From 475e34d774091903feafec75d1d803857b3d6a2b Mon Sep 17 00:00:00 2001 From: David Date: Tue, 25 Apr 2017 23:44:33 +0300 Subject: [PATCH 11/12] Fixes --- SoftCache/src/SoftCacheMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SoftCache/src/SoftCacheMap.java b/SoftCache/src/SoftCacheMap.java index 0fee49a..80e65f5 100644 --- a/SoftCache/src/SoftCacheMap.java +++ b/SoftCache/src/SoftCacheMap.java @@ -9,7 +9,7 @@ public class SoftCacheMap implements Cache { private HashMap> cache; private HashMap, HashSet> subsidiaryMap; - private ReferenceQueue referenceQueue; + private ReferenceQueue referenceQueue; private Deque recentlyUsed; private int maxSize; private int cleaningFrequency; From 6ebecef69868835e883490893ee203eb12e45982 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 1 May 2017 12:13:10 +0300 Subject: [PATCH 12/12] Unit-test added --- SoftCache/.gitignore | 1 + SoftCache/pom.xml | 100 ++++++++++++++++++ .../src/{ => main/java/maven}/Cache.java | 5 +- .../{ => main/java/maven}/SoftCacheMap.java | 57 +--------- .../src/main/resources/log4j2.properties | 7 ++ .../src/test/java/maven/SoftCacheMapTest.java | 93 ++++++++++++++++ 6 files changed, 207 insertions(+), 56 deletions(-) create mode 100644 SoftCache/.gitignore create mode 100644 SoftCache/pom.xml rename SoftCache/src/{ => main/java/maven}/Cache.java (92%) rename SoftCache/src/{ => main/java/maven}/SoftCacheMap.java (71%) create mode 100644 SoftCache/src/main/resources/log4j2.properties create mode 100644 SoftCache/src/test/java/maven/SoftCacheMapTest.java diff --git a/SoftCache/.gitignore b/SoftCache/.gitignore new file mode 100644 index 0000000..ffd2a4a --- /dev/null +++ b/SoftCache/.gitignore @@ -0,0 +1 @@ +*.idea diff --git a/SoftCache/pom.xml b/SoftCache/pom.xml new file mode 100644 index 0000000..d2a7ca6 --- /dev/null +++ b/SoftCache/pom.xml @@ -0,0 +1,100 @@ + + + + 4.0.0 + + maven + softCache + jar + 1.0 + + A Camel Route + + + UTF-8 + UTF-8 + + + + + + + org.apache.camel + camel-parent + 2.18.3 + import + pom + + + + + + + + org.apache.camel + camel-core + + + + + org.apache.logging.log4j + log4j-api + runtime + + + org.apache.logging.log4j + log4j-core + runtime + + + org.apache.logging.log4j + log4j-slf4j-impl + runtime + + + + + org.apache.camel + camel-test + test + + + + + install + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-resources-plugin + 3.0.1 + + UTF-8 + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.5.0 + + maven.MainApp + false + + + + + + + diff --git a/SoftCache/src/Cache.java b/SoftCache/src/main/java/maven/Cache.java similarity index 92% rename from SoftCache/src/Cache.java rename to SoftCache/src/main/java/maven/Cache.java index ea03777..ab5fcb1 100644 --- a/SoftCache/src/Cache.java +++ b/SoftCache/src/main/java/maven/Cache.java @@ -1,6 +1,5 @@ -/** - * Created by david on 18.04.17. - */ +package maven; + public interface Cache { /** * Возвращает соответствующее значение, если оно ещё в кэше, иначе null diff --git a/SoftCache/src/SoftCacheMap.java b/SoftCache/src/main/java/maven/SoftCacheMap.java similarity index 71% rename from SoftCache/src/SoftCacheMap.java rename to SoftCache/src/main/java/maven/SoftCacheMap.java index 80e65f5..4b4616c 100644 --- a/SoftCache/src/SoftCacheMap.java +++ b/SoftCache/src/main/java/maven/SoftCacheMap.java @@ -1,3 +1,5 @@ +package maven; + import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.Deque; @@ -15,7 +17,7 @@ public class SoftCacheMap implements Cache { private int cleaningFrequency; private int numOfPuts; - private SoftCacheMap(int size, int frequency) { + protected SoftCacheMap(int size, int frequency) { cache = new HashMap<>(); /** * второй hashMap - вспомогательный, используется при удалении из кэша @@ -106,55 +108,4 @@ public void clear() { subsidiaryMap.clear(); } - public static void main(String... args) throws InterruptedException { - - /** - * проверка корректной работы referenceQueue - */ - - SoftCacheMap cache1 = new SoftCacheMap(0, 1); - cache1.put(0, new Integer(0)); - - /** - * должен быть 0 - */ - System.out.println(cache1.getIfPresent(0)); - - try { - Object[] big = new Object[(int) Runtime.getRuntime().maxMemory()]; - } catch (OutOfMemoryError e) { - // ignore - } - - /** - * должен быть null - */ - System.out.println(cache1.getIfPresent(0)); - cache1.clear(); - - - /** - * проверка корректной работы recentlyUsed - */ - - SoftCacheMap cache2 = new SoftCacheMap(1, 1); - cache2.put(0, new Integer(0)); - - /** - * должен быть 0 - */ - System.out.println(cache2.getIfPresent(0)); - - try { - Object[] big = new Object[(int) Runtime.getRuntime().maxMemory()]; - } catch (OutOfMemoryError e) { - // ignore - } - - /** - * должен быть 0 - */ - System.out.println(cache2.getIfPresent(0)); - cache2.clear(); - } -} \ No newline at end of file +} diff --git a/SoftCache/src/main/resources/log4j2.properties b/SoftCache/src/main/resources/log4j2.properties new file mode 100644 index 0000000..328db35 --- /dev/null +++ b/SoftCache/src/main/resources/log4j2.properties @@ -0,0 +1,7 @@ + +appender.out.type = Console +appender.out.name = out +appender.out.layout.type = PatternLayout +appender.out.layout.pattern = [%30.30t] %-30.30c{1} %-5p %m%n +rootLogger.level = INFO +rootLogger.appenderRef.out.ref = out diff --git a/SoftCache/src/test/java/maven/SoftCacheMapTest.java b/SoftCache/src/test/java/maven/SoftCacheMapTest.java new file mode 100644 index 0000000..4cfd06a --- /dev/null +++ b/SoftCache/src/test/java/maven/SoftCacheMapTest.java @@ -0,0 +1,93 @@ +package maven; + +import org.junit.Assert; +import org.junit.Test; +import java.util.ArrayList; +import java.util.Arrays; + +public class SoftCacheMapTest { + + private SoftCacheMap getCache(int size, int frequency) { + return new SoftCacheMap<>(size, frequency); + } + + private void testBefore(int size, int frequency, ArrayList values, + ArrayList expectedBefore) throws Exception { + + String errorMessage = "Bad result"; + SoftCacheMap cache = getCache(size, frequency); + for (int i = 0; i < values.size(); ++i) { + cache.put(i, values.get(i)); + } + for (int i = 0; i < values.size(); ++i) { + Assert.assertEquals(errorMessage, expectedBefore.get(i), cache.getIfPresent(i)); + } + } + + private void testAfter(int size, int frequency, ArrayList values, + ArrayList expectedAfter) { + String errorMessage = "Bad result"; + SoftCacheMap cache = getCache(size, frequency); + for (int i = 0; i < values.size(); ++i) { + cache.put(i, new Integer(values.get(i))); + } + try { + Object[] big = new Object[(int) Runtime.getRuntime().maxMemory()]; + } catch (OutOfMemoryError e) { + // ignore + } + + int counter = 0; + for (int i = 0; i < values.size(); ++i) { + if (cache.getIfPresent(i) != null) { + Assert.assertEquals(errorMessage, expectedAfter.get(counter), cache.getIfPresent(i)); + ++counter; + } + } + } + + @Test + public void testReferenceQueueBefore() throws Exception { + ArrayList values = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5)); + ArrayList expectedBefore = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5)); + testBefore(0, 1, values, expectedBefore); + } + + @Test + public void testReferenceQueueAfter() throws Exception { + ArrayList values = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5)); + testAfter(0, 1, values, null); + } + + @Test + public void testRecentlyUsedQueueAfter0() throws Exception { + ArrayList values = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5)); + ArrayList expectedAfter = new ArrayList<>(Arrays.asList(4, 5)); + testAfter(2, 1, values, expectedAfter); + } + + @Test + public void testRecentlyUsedQueueAfter1() throws Exception { + ArrayList values = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5)); + ArrayList expectedAfter = new ArrayList<>(Arrays.asList(2, 5)); + String errorMessage = "Bad result"; + SoftCacheMap cache = getCache(2, 1); + for (int i = 0; i < values.size(); ++i) { + cache.put(i, new Integer(values.get(i))); + } + cache.getIfPresent(2); + try { + Object[] big = new Object[(int) Runtime.getRuntime().maxMemory()]; + } catch (OutOfMemoryError e) { + // ignore + } + + int counter = 0; + for (int i = 0; i < values.size(); ++i) { + if (cache.getIfPresent(i) != null) { + Assert.assertEquals(errorMessage, expectedAfter.get(counter), cache.getIfPresent(i)); + ++counter; + } + } + } +}