[英]Using HashMap.keySet as a dirty copy
我有一个必须使用hashMap的要求,其中值可以动态更改,并且键只能插入而不删除或更新。 但是,将多次读取键,并且可能会多次更新值。
对于延迟问题,我没有将整个HashMap做成ConcurrentHashMap,在这种情况下,编写密钥时会遇到问题。 我可以通过密钥来降低数据的准确性。 因此,我决定保留自己的脏密钥副本。 如下所示的代码段。
package com.test.collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
public class CheckKeySet {
private static Map<String, ConcurrentHashMap<String, String>> testMap = new HashMap<String, ConcurrentHashMap<String, String>>();
public static void main(String[] args) {
CheckKeySet trial = new CheckKeySet();
try {
trial.doIt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void doIt() throws InterruptedException {
Thread accessThread1 = new AccessKeySet("Access1");
Thread writeThread = new WriteValueSet();
Thread accessThread2 = new AccessKeySet("Access2");
Thread accessThread3 = new AccessKeySet("Access3");
writeThread.start();
Thread.sleep(1000);
accessThread1.start();
Thread.sleep(2000);
accessThread2.start();
Thread.sleep(4000);
accessThread3.start();
}
private Set<String> getKeySet() {
return new TreeSet<String>(testMap.keySet());
}
class AccessKeySet extends Thread {
public AccessKeySet(String string) {
super(string);
}
@Override
public void run() {
Set<String> keySet = getKeySet();
System.out.println("###############Trying to print########## " + getName() + " keySet size " + keySet.size());
for (String s : keySet) {
System.out.println(s);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class WriteValueSet extends Thread {
@Override
public void run() {
int i = 1;
for (i = 1; i < 10000; i++) {
testMap.put("Check-" + i, new ConcurrentHashMap<String, String>());
System.out.println("Inserted " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
我的问题是,我在上述实现中使用HashMap.keySet()作为基值来创建新的Set对象。 HashMap.keySet()将永远存在于我的代码中。 这会影响我在getKeySet()中创建的脏集对象的GC吗? 我希望只要它的持有对象有资格使用gc,就可以抄送这个新的set对象。 由于hashMap.keySet仍然存在,因此不应停止获取gced
如果我错了,请纠正我,但听起来您不希望从testMap
收集垃圾或键或值,除非您手动将其删除。 相反,您只希望对getKeySet()
方法返回的键集中的键进行垃圾回收,即使可能的话,即使您可能不明确地从键集中删除它们也是如此。
假设是这种情况,您应该考虑使用弱引用 。 对于实现而言,您可以模拟一个WeakHashSet
(按照此答案 ),并将您的getKeySet()
方法实现更改为:
private Set<String> getKeySet() {
Set<String> cache = Collections.newSetFromMap(
new WeakHashMap<String, Boolean>());
cache.addAll(this.testMap.keySet());
return cache;
}
此新代码将强引用的testMap
所有键testMap
到弱引用的cache
。 因此,每当从testMap
删除元素后运行垃圾收集器时,垃圾收集器都会从cache
自动删除该元素。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.