直接上代码
缓存对象
import org.apache.log4j.Logger; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * 基于软引用实现的缓存,当内存不够使会自动释放缓存内容,以避免OOM * User: yfzhangbin * Date: 13-8-16 * Time: 下午4:02 */ public class SoftReferenceCache<K, V> { private static final Logger log = Logger.getLogger(SoftReferenceCache.class); private Map<K, InnerSoftReference<V>> cache; // 缓存对象池,<K, R->V> private ReferenceQueue<V> queue; // 引用队列,当GC执行后被回收的缓存对象的软引用将被入队,以方便从缓存池中清除失效的软引用。 private ReadWriteLock lock; // 读写锁 public SoftReferenceCache() { cache = new HashMap<K, InnerSoftReference<V>>(); queue = new ReferenceQueue<V>(); lock = new ReentrantReadWriteLock(false); } /** * 向缓存池中添加对象 * @param key * @param value */ public void put(K key, V value) { try { lock.writeLock().lock(); clearInvalidReference(); cache.put(key, new InnerSoftReference<V>(key, value, queue)); } finally { lock.writeLock().unlock(); } } /** * 从缓存池中获取对象 * @param key * @return */ public V get(K key) { try { lock.readLock().lock(); InnerSoftReference<V> softReference = cache.get(key); V v = null; if (softReference != null) v = softReference.get(); return v; } finally { lock.readLock().unlock(); } } /** * 从缓存池中清除失效的软引用 * 备注:失效软引用是指向null的引用 */ private void clearInvalidReference() { InnerSoftReference<V> softReference; while ((softReference = (InnerSoftReference)queue.poll()) != null) { if (softReference.get() == null) cache.remove(softReference.getKey()); } } /** * 缓存池中对象的个数 * @return */ public int size() { try { lock.readLock().lock(); int size = cache.size(); log.info(Thread.currentThread().getName() + " 缓存池中对象的个数: " + size); return size; } finally { lock.readLock().unlock(); } } /** * 清空缓存池,定时worker每次计算前调用此方法可清除历史记录 */ public void clearCache() { try { lock.writeLock().lock(); cache = new HashMap<K, InnerSoftReference<V>>(); queue = new ReferenceQueue<V>(); log.info(Thread.currentThread().getName() + "清空缓存池!"); } finally { lock.writeLock().unlock(); } } /** * 封装了软引用,便于获取对应缓存池中的key * @param <V> */ private class InnerSoftReference<V> extends SoftReference<V> { private K key; private InnerSoftReference(K key, V value, ReferenceQueue<V> queue) { super(value, queue); this.key = key; } public K getKey() { return key; } } }
测试类
import com.jd.recommend.service.util.*; import org.apache.log4j.Logger; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 测试类 * User: yfzhangbin * Date: 13-8-16 * Time: 下午5:18 */ public class TestSoftReferenceCache { private static final Logger log = Logger.getLogger(TestSoftReferenceCache.class); private static int MAX_COUNT = 100000; private static String KEY_PREFIX = "KEY_"; private static SoftReferenceCache<String, byte[]> cache = new SoftReferenceCache<String, byte[]>(); public static void main(String[] args) { ExecutorService es = Executors.newCachedThreadPool(); es.submit(new Customer()); es.submit(new Customer()); es.submit(new Customer()); es.submit(new Customer()); es.submit(new Customer()); es.shutdown(); } static class Customer implements Runnable { @Override public void run() { while (true) { for (int i = 0; i < MAX_COUNT; i ++) { byte[] a = cache.get(KEY_PREFIX + i); if (a == null) { a = new byte[1024]; cache.put(KEY_PREFIX + i, a); log.info(Thread.currentThread().getName() + " 向缓存池中添加对象[" + (KEY_PREFIX + i) + "]: " + a); } else { log.info(Thread.currentThread().getName() + " 从缓存池中获取对象[" + (KEY_PREFIX + i) + "]: " + a); } } } } } }
相关推荐
4. 清理缓存:当系统内存紧张时,垃圾回收器会回收软引用的对象,`BitmapCache`应监听到这种变化并及时清理对应的缓存条目,以保持缓存的健康状态。 四、优化建议 1. 使用适当的图片尺寸:在加载图片时,根据显示...
Android中常见的内存缓存实现是使用LRU(Least Recently Used)算法,当内存不足时,会优先移除最近最少使用的图片。`ImagesCache`可能就采用了这种策略,确保高效且避免内存浪费。 SDCard缓存: 当内存缓存不足以...
本文将深入探讨如何实现一个高效、安全的网络图片加载机制,结合双缓存策略,确保图片加载过程既快速又不会导致内存溢出(Out Of Memory, OOM)。 首先,我们要理解为什么需要异步加载。在Android中,如果在主线程...
本教程将详细探讨如何在Android中有效地进行图片下载和内存处理,以避免OOM的发生。 1. **图片下载**: - 使用高效的图片下载库:如Glide、Picasso或Fresco。这些库具有自动缓存机制,能够减少网络请求,提高用户...
Glide是一款强大的图片加载库,它内部实现了内存和磁盘缓存,可以自动处理Bitmap的内存管理,防止OOM。 3. 使用Picasso或 Fresco:Picasso和Fresco都是优秀的图片加载库,它们能智能地处理图片的缩放、缓存和内存...
当内存不足时,系统会自动清理LRUCache中最不常用的数据。 2. **磁盘缓存**:利用SQLite数据库或文件系统存储图片数据。当图片从网络下载后,可以先写入磁盘,下次加载时直接读取。 3. **加载逻辑**:实现图片加载...
在安卓开发中,图片处理是一项常见且重要的任务,然而,如果不妥善处理,它可能会导致一个严重的问题——内存溢出(Out Of Memory,简称OOM)。内存溢出是由于程序请求的内存超过了系统分配的最大内存,从而导致程序...
一旦内存不足,系统会自动清理这部分数据。 2. **磁盘缓存**:当内存缓存不足以存储所有图片时,图片会被存储到磁盘上。虽然访问速度较慢,但容量较大,不会轻易被清理。 3. **网络缓存**:如果图片不在内存或磁盘...
LRU(Least Recently Used)算法是一种常用的页面替换策略,它基于“最近最少使用”的原则,即当内存空间不足时,最长时间未被使用的数据会被优先淘汰。在Android开发中,由于内存有限,处理大量图片可能导致内存...
在用户滚动列表或浏览大量图片时,如果没有合适的缓存机制,可能会导致内存溢出(OOM)或者用户体验下降,因为频繁的网络请求会使应用显得卡顿。本篇文章将深入探讨Android图片缓存的实现,特别是利用软硬引用进行的...
当系统内存不足时,垃圾回收器会回收软引用指向的对象,以防止系统出现内存溢出(OOM)。软引用常用于实现缓存,例如上述提到的图片缓存例子。通过使用软引用,可以实现内存敏感的缓存策略,即在内存充足时缓存对象...
它们内部实现了内存缓存和磁盘缓存策略,当图片首次加载时,会下载到内存缓存,如果内存不足,会被存储到磁盘缓存。再次请求同一图片时,可以直接从缓存中读取,减少了网络请求,提高了用户体验。 缓存机制是防止...
然而,当系统内存不足时,垃圾回收器会清除这些软引用指向的对象,以便释放内存,防止系统出现OOM异常。 **Android OOM问题** 在Android中,每个应用程序都有一定的内存预算,当应用程序的内存使用超出这个预算时,...
使用LRU(Least Recently Used)缓存策略,当内存不足时,优先移除最近最少使用的图片,以保持内存的合理使用。 7. 文件流加载 不要将整个图片加载到内存中,而是使用文件流分块加载,只加载可视部分。 8. 使用...
通过使用软引用或弱引用,可以在内存不足时自动释放Bitmap,从而防止内存泄漏和OOM的发生。例如,可以创建一个持有Bitmap的软引用,当系统需要回收内存时,Bitmap会被自动回收,而不是一直占用内存。 ```java ...
它能够自动加载图片,并在不需要时自动释放内存,避免了大量图片缓存在内存中导致的内存溢出。这种机制特别适用于处理大批量图片的应用,如电商应用中的商品展示。 3. **防止OOM**:通过智能地缓存图片到内存和磁盘...
内存缓存通常使用LRU(Least Recently Used)算法来管理,当内存不足时,会优先移除最近最少使用的图片。磁盘缓存一般位于外部存储器,通过SQLite数据库或文件系统实现。Glide提供了自定义缓存策略的接口,开发者...
使用LruCache和DiskLruCache缓存资源,有效避免OOM,加载再多图片也不会顿卡,非常流畅,不会内存不够,到底有多牛谁运行谁知道。
当应用需要加载图片时,首先会尝试从内存缓存中查找,如果找不到,则从磁盘缓存中读取,如果磁盘缓存也没有,再从网络或本地文件系统加载,并将图片存入两级缓存中,以便后续使用。 二、内存缓存 内存缓存通常使用...