在单机版系统中需要实现一个简单的缓存功能(不使用分布式缓存系统),在内存中用一个map来实现就行了,通常的map可用 LinkedHashMap也可以用WeakHashMap 来实现,他们的区别在于淘汰机制上,前者是在构建时设置一个阀值(或者是可以在回收的时候决定那个对象优先被回收),当到了一个阀值之后就会决定老的对象是否要被淘汰。而后者WeakHashMap 是基于虚拟机的垃圾回机制来淘汰的,回收时,容器中哪个对象对回收完全是由GC来决定的。
这里通过一些代码来来说明WeakHashMap的特性,首先第一个代码,可以顺利执行完成:
public void test1() throws Exception { //List<byte[][]> keys = new ArrayList<byte[][]>(); byte[][] key = null; WeakHashMap<byte[][], byte[][]> maps = new WeakHashMap<byte[][], byte[][]>(); for (int i = 0; i < 10000; i++) { key = new byte[1000][1000]; maps.put(key, new byte[1000][1000]); // System.gc(); System.err.println(i); System.err.println(" size" + maps.size()); } }
从输出结果上可以发现,size的大小,会由小变大,突然变小,然后再由小变大。这个说明垃圾回收期在器作用,这个和jdk的说明文档是一致的:
/ * An entry in a <tt>WeakHashMap</tt> will automatically be removed when * its key is no longer in ordinary use. More precisely, the presence of a * mapping for a given key will not prevent the key from being discarded by the * garbage collector, that is, made finalizable, finalized, and then reclaimed. * When a key has been discarded its entry is effectively removed from the map, * so this class behaves somewhat differently from other <tt>Map</tt> * implementations. */
当GC开始回收的时候会发现,map的key已经不被使用了,即使map中key和value的映射已然存在,也不能阻止map的key被GC回收掉。当map的key被回收了之后,value对象也会被顺利地回收的。
再看下面这个代码:
public void test2() throws Exception { List<byte[][]> keys = new ArrayList<byte[][]>(); byte[][] key = null; WeakHashMap<byte[][], byte[][]> maps = new WeakHashMap<byte[][], byte[][]>(); for (int i = 0; i < 10000; i++) { key = new byte[1000][1000]; keys.add(key); maps.put(key, new byte[1000][1000]); // System.gc(); System.err.println(i); System.err.println(" size" + maps.size()); } }
test2()执行到一半就会抛出OOM异常,这份代码和上一份代码的唯一区别就是,map的key放到一个list中,这样能保证方法体中的所有key都是被引用的,所以在启动垃圾回收的时候,weak中的key一个都不会被自动回收,所以OOM就在所难免了。
所以在使用WeakHashMap的时候,千万注意,使用完某个key如果希望对象会被自动回收,需要与map的key的所有引用关系切断。
相关推荐
WeakHashMap的使用方法详解 WeakHashMap是Java中的一种哈希映射表,它的键是弱引用的,意味着当 WeakHashMap 的键对象只有 WeakHashMap 自己持有时,垃圾回收器可以将其回收。WeakHashMap 的使用方法主要体现在...
WeakHashMap是Java中的一种特殊的哈希表实现,它使用弱引用(Weak Reference)来保存键对象。当键对象没有被其他强引用引用时,在垃圾回收时会自动从WeakHashMap中移除对应的键值对。
WeakHashMap是Java编程中的一种特殊的HashMap实现,它使用弱引用来保存键和值,这样可以使得垃圾回收器自动清理键和值。在WeakHashMap中,键和值都是弱引用的,这样可以避免内存泄露的问题。 WeakHashMap的实现...
《Java 理论与实践: 用弱引用堵住内存泄漏》一文也指出了使用全局的Map作为缓存容器时发生的内存泄露问题,介绍了如何使用hprof工具来找出内存泄露,并分析了如何使用弱引用来防止内存泄露,还分析了
可以使用 Java 的 API 来实现对象的缓存,例如使用 WeakHashMap 来实现缓存。 7. profiling 工具的使用 profiling 工具是优化 Java 进程的内存占用的一种重要方法。例如,可以使用 VisualVM、JProfiler 等 ...
### 弱类型语言的概念及其特点 #### 一、弱类型语言定义 弱类型语言是指一种编程语言特性,这种语言允许程序在运行时自动转换...然而,使用 WeakHashMap 时需要注意其自动清理机制的触发条件,以避免内存泄漏等问题。
WeakHashMap 则使用弱引用作为键,有助于防止内存泄漏。 - 在选择使用哪种数据结构时,需要考虑性能需求、线程安全性以及是否允许重复元素等因素。例如,如果需要高并发且线程安全,可以选择 Vector 或者同步控制的 ...
同时,可以自定义缓存策略,如使用`WeakHashMap`作为内存缓存,配合`SharedPreferences`或文件系统实现磁盘缓存。 总的来说,Android异步加载图像涉及到多线程编程、缓存策略以及性能优化等多个方面。通过合理使用...
3. **使用更细粒度的锁**:将大锁拆分为小锁,减少锁竞争,降低死锁风险。 4. **优化循环和计算**:减少不必要的循环,优化计算逻辑,避免CPU过度使用。 5. **监控与调试**:使用Java的JMX、VisualVM等工具监控线程...
- **WeakHashMap**:使用WeakHashMap可以优化垃圾收集,键被弱引用,一旦没有强引用,就会被垃圾回收。 3. **I/O操作**: - **字节流 vs 字符流**:字节流处理性能通常优于字符流,尤其是在处理二进制数据时。 -...
同时,对于图片的三级缓存,可以使用独立的内存缓存(如LruCache或WeakHashMap)和文件缓存(如SQLite或文件系统)来分别存储。文件缓存通常包括图片的原始数据和可能的缩略图,以适应不同场景下的显示需求。 总的...
TreeMap则按照Key进行排序,而WeakHashMap使用弱引用键,有助于防止内存泄漏。 4. ConcurrentHashMap和Hashtable:ConcurrentHashMap是线程安全的Map,采用了分段锁策略,比Hashtable在多线程环境下表现更优。它在...
标题中的“查词测试的一个小工具”表明这是一个用于测试词汇查询功能的应用程序,可能是为了检验特定的Java版本中字典操作或字符串处理的性能。描述中的“dict of java version ,only for test”进一步确认了这个...
WeakHashMap是一种特殊的哈希表,它使用弱引用作为键,当键不再被引用时,即使没有显式地从集合中移除,也会自动清理。 **Map接口** Map接口存储键值对,不直接继承自Collection接口。常见的Map实现有Hashtable、...
- 使用`LruCache`或`WeakHashMap`实现内存缓存,存储图片的Bitmap对象。内存缓存速度快,但容量有限,需根据设备内存大小合理设置缓存容量。 2. 磁盘缓存: - 使用`DiskLruCache`或者`OkHttp`自带的`Cache`实现...
在WeakHashMap中,当某个键不再正常使用时,将自动移除其条目。 Java集合类提供了多种实现,用于解决不同的数据存储和操作问题。开发者可以根据实际情况选择合适的集合类实现,提高程序的效率和可维护性。
在标准的Java库中,IdentityHashMap依赖对象的引用地址(而非equals()方法)来确定键值对的唯一性,而WeakHashMap则使用弱引用,当键被垃圾收集器回收时,键值对也会自动从映射中移除。 WeakIdentityHashMap则是将...
2. **缓存与重用对象**:对于一些昂贵的计算结果或者常量,可以使用缓存技术(如`WeakHashMap`或`Guava`库的`Cache`)来存储,避免重复计算。例如,使用`Integer.valueOf(int)`代替`new Integer(int)`,因为前者会...
7. **有效利用缓存**:使用`java.util.concurrent`包下的`ConcurrentHashMap`或`WeakHashMap`进行缓存,避免全表扫描。 8. **避免过度使用synchronized**:虽然同步可以保证线程安全,但也会导致性能下降。可以考虑...