昨天在我们的系统中看到了这样的一行代码:
private final Map<String, String> CACHE = new WeakHashMap();
对于
WeakHashMap
而言,之前还真的没有听过,
惭愧啊!晚上就好好的研究了下,这个不对不说说强引用、软引用、弱引用、虚引用以及垃圾回收了。
1. 强引用、软引用、弱引用、虚引用
1)强引用:就是我们平时写的new了,如Object o = new Object(),这里有两点请注意,一个是o,另一个是Object。这里假设这行代码是在方法体里写的(局部和全局是有相当大的区别的),那么o就是存储在栈空间里,而Object对象是存储在堆空间里,o就是Object对象的引用了。如果o的生命周期一直存在,那么Object对象是一直不会被回收的,即使空间不足了,它也不会回收,宁愿抛出 OutOfMemery的异常。现在是写在方法体里了,当调用这个方法结束时,o的生命周期就结束了,此时Ojbect对象就没有引用了,垃圾回收器就会将它进行回收,具体在什么时候回收,我们就不得而知了。
2)软引用:它的特征是空间足够,不会回收,空间不足够,就会回收。垃圾回收器在回收之前做了一个操作,就是将其引用置为null了。
3)弱引用:它的特征是不管空间是否足够,它都有可能被会垃圾回收器回收。
4)虚引用:它本质是在垃圾回收后进行一定的辅助操作,它不涉及对象的生命周期。
2.WeakHashMap
WeakHashMap,从字面上看,就知道,它是一个弱引用,它其实也是一个Map,不过它有一个特征就是:当key的对象
不可用时,它的key-value就会被回收。这里的不可用,是什么意思呢?就是这个key的对象是非强引用时,它就会变成不可用。下面会给出相应的例子来讲解。
public static void main(String args[]) throws ClassNotFoundException, SQLException, InterruptedException {
Map<String, String> cache = new WeakHashMap();
String key=null;
try(Connection connection = DBConnection.getConnection()){
try (PreparedStatement pstmt = connection
.prepareStatement("SELECT F01,F02 FROM Table LIMIT 1")) {
try (ResultSet resultSet = pstmt.executeQuery()) {
if (resultSet.next()) {
System.out.println("F01 = " +resultSet.getString(1));
// key=resultSet.getString(1); // --(1)
// cache.put(key, resultSet.getString(2)); // --(2)
cache.put(resultSet.getString(1),resultSet.getString(2)); // --(3)
}
}
}
}
while(true){
System.gc();
Thread.sleep(50000);
System.out.println("get value:"+cache.get("BAOFUPAY.BF_CHARGE_PAGEURL"));
}
}
请注意:
1)如果将 1),2)注释掉,则输出的结果为null;
2)如果将3)注释掉,1) 2) 打开则输出的结果为key的value值。
怎么是这样的呢?这是因为
resultSet.getString(1)
,它是匿名对象,是没有引用的,这个key很快就会变成不可用,如果有一个key的变量,如上面所写,
key=resultSet.getString(1)
,它就变成了一个强引用了,此时就不可能被回收了。