关于WeakHashMap

对DataBox作同步操作,需要加锁,每个DataBox对应一把锁,当然你可以new一个TDataBox 再new 一个Locker,但为了简便,我准备用一个全局的Map管理box,locker集合,自动为内存中的每一个dataBox匹配一个locker。这种情况如果使用普通的hashMap会有问题(box在map中被引用,即使这个box不被其他对象引用,内存也释放不了),使用WeakHashMap可以解决这个问题
public static Map<TDataBox, Locker> lockers = Collections.synchronizedMap(new WeakHashMap<TDataBox, Locker>());

public static Locker getLocker(TDataBox box, boolean createLocker){
Locker locker = lockers.get(box);
if(locker == null && createLocker){
locker = new Locker();
lockers.put(box, locker);
}
return locker;
}

public static void invokeChange(Runnable run, TDataBox box){
Locker locker = getLocker(box, true);
executeChange(run, locker);
}

public static void invokeRead(Runnable run, TDataBox box){
Locker locker = getLocker(box, true);
executeRead(run, locker);
}

WeakHashMap有什么作用呢,WeakHashMap<key, value>,当key不被其他对象引用时,map中对应的这一项会自动(内存不足或者System.gc()时)回收

下面测试例子:

public static void main(String[] args) throws InterruptedException {
Map<TDataBox, byte[]> lockers = Collections.synchronizedMap(new WeakHashMap<TDataBox, byte[]>());
// Map<TDataBox, byte[]> lockers = Collections.synchronizedMap(new HashMap<TDataBox, byte[]>());

System.out.println(Runtime.getRuntime().totalMemory());

for(int i = 0; i < 100; i++){
lockers.put(new TDataBox(""+i), new byte[2048000]);
System.gc();
Thread.sleep(200);
System.out.println("lockers.size() : " + lockers.size());
System.out.println(Runtime.getRuntime().totalMemory());
System.gc();
}
}
输出:
83230720
lockers.size() : 0
83230720
lockers.size() : 0
83230720
lockers.size() : 0
83230720
lockers.size() : 0
将System.gc()注释调,输出结果:
83230720
lockers.size() : 1
83230720
lockers.size() : 2
83230720
lockers.size() : 3
83230720
lockers.size() : 4
83230720
lockers.size() : 5
83230720
lockers.size() : 6
83230720
lockers.size() : 7
83230720
lockers.size() : 1
83230720
lockers.size() : 2
83230720
lockers.size() : 3
改用HashMap,outOfMemory


八 + = 16