- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
强引用(Strong Reference)是我们使用最多的一种对象引用,当一个对象被关键字 new 实例化出来的时候, JVM 会在堆(heap)内存中开辟一个内存区域,用于存放与该实例对应的数据结构。JVM 垃圾回收器线程会在达到 GC 条件的时候尝试回收(Full GC,Young GC)堆栈内存中的数据,强引用的特点是只要引用到 Root 根的路径可达,无论怎样的 GC 都不会将其释放,而是宁可出现 JVM 内存溢出。
Cache 是一种用于提高系统性能,提高数据检索效率的机制,而 LRU(Least recently used,最近最少使用)算法和 Cache 的结合是最常见的一种 Cache 实现。
LRU 是数据冷热治理的一种思想,不经常使用的数据被称为冷数据,经常使用的则被称为热数据,对冷数据分配提前释放,可以帮助我们节省更多的内存资源,LRUCache 的实现方式有很多种,在这里使用双向链表+hash表的方式来实现。
package concurrent.lrucache.strongRefercence;
/**
* @className: Reference
* @description: 当 Reference 对象被实例化后,会在堆内存中创建 1M 的内存空间
* @date: 2022/4/28
* @author: cakin
*/
public class Reference {
// 1M
private final byte[] data = new byte[2 << 19];
/**
* 功能描述:会在垃圾回收的标记阶段被调用,垃圾回收器在回收一个对象之前,首先会进行标记,标记的过程会调用该对象的 finalize 方法
* 所以千万不要认为该方法被调用之后,就代表对象已被垃圾回收器回收,对象在 finalize 方法中是可以”自我救赎“的。
*
* @author cakin
* @date 2022/4/28
* @description:
*/
@Override
protected void finalize() throws Throwable {
System.out.println("the reference will be GC");
}
}
package concurrent.lrucache.strongRefercence;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
/**
* @className: LRUCache
* @description: 最近最少使用缓存
* @date: 2022/4/28
* @author: cakin
*/
public class LRUCache<K, V> {
// 用于记录 key 值的顺序
private final LinkedList<K> keyList = new LinkedList<>();
// 用于存放数据
private final Map<K, V> cache = new HashMap<>();
// cache 的最大容量
private final int capacity;
// 提供了一种加载数据的方式
private final CacheLoader<K, V> cacheLoader;
public LRUCache(int capacity, CacheLoader<K, V> cacheLoader) {
this.capacity = capacity;
this.cacheLoader = cacheLoader;
}
public void put(K key, V value) {
// 当元素数量超过容量时,将最老的数据清除
if (keyList.size() >= capacity) {
K eldestkey = keyList.removeFirst(); // eldest data
cache.remove(eldestkey);
}
// 如果数据已经存在,则从 key 的队列中删除
if (keyList.contains(key)) {
keyList.remove(key);
}
// 将 key 存放到队尾
keyList.addLast(key);
cache.put(key, value);
}
public V get(K key) {
V value;
// 先将 key 从 key list 中删除
boolean success = keyList.remove(key);
// 如果删除失败则表明该数据不存在
if (!success) {
// 通过 cacheLoader 对数据进行加载
value = cacheLoader.load(key);
// 通过 put 方法 cache 数据
this.put(key, value);
} else {
// 如果删除成功,则从 cache 中返回数据,并且将 key 再次放到队尾
value = cache.get(key);
keyList.addLast(key);
}
return value;
}
@Override
public String toString() {
return this.keyList.toString();
}
}
package concurrent.lrucache.strongRefercence;
@FunctionalInterface
public interface CacheLoader<K, V> {
// 定义加载数据的方法
V load(K k);
}
package concurrent.lrucache.strongRefercence;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) {
test1();
test2();
}
private static void test1() {
LRUCache<String, Reference> cache = new LRUCache<>(5, key -> new Reference());
cache.get("1");
cache.get("2");
cache.get("3");
cache.get("4");
cache.get("5");
cache.get("6");
System.out.println(cache.toString());
}
private static void test2() {
LRUCache<Integer, Reference> cache1 = new LRUCache<>(200, key -> new Reference());
for (Integer i = 0; i < Integer.MAX_VALUE; i++) {
cache1.get(i);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("The " + i + " reference stored at cache.");
}
}
}
[2, 3, 4, 5, 6]
取缓存时,把最老的数据 1 给踢掉
-Xmx128M -Xms64M -XX:+PrintGCDetails
......
The 93 reference stored at cache.
The 94 reference stored at cache.
The 95 reference stored at cache.
The 96 reference stored at cache.
The 97 reference stored at cache.
The 98 reference stored at cache.
[Full GC (Ergonomics) [PSYoungGen: 15677K->15362K(18944K)] [ParOldGen: 87227K->87226K(87552K)] 102904K->102589K(106496K), [Metaspace: 4683K->4683K(1056768K)], 0.0071742 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full GC (Allocation Failure) [PSYoungGen: 15362K->15362K(18944K)] [ParOldGen: 87226K->87226K(87552K)] 102589K->102589K(106496K), [Metaspace: 4683K->4683K(1056768K)], 0.0028789 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
PSYoungGen total 18944K, used 16002K [0x00000000fd580000, 0x0000000100000000, 0x0000000100000000)
eden space 16384K, 97% used [0x00000000fd580000,0x00000000fe520860,0x00000000fe580000)
from space 2560K, 0% used [0x00000000fe580000,0x00000000fe580000,0x00000000fe800000)
to space 14336K, 0% used [0x00000000ff200000,0x00000000ff200000,0x0000000100000000)
ParOldGen total 87552K, used 87226K [0x00000000f8000000, 0x00000000fd580000, 0x00000000fd580000)
object space 87552K, 99% used [0x00000000f8000000,0x00000000fd52ea90,0x00000000fd580000)
Metaspace used 4715K, capacity 4882K, committed 4992K, reserved 1056768K
class space used 523K, capacity 559K, committed 640K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at concurrent.lrucache.strongRefercence.Reference.<init>(Reference.java:11)
at concurrent.lrucache.strongRefercence.Test.lambda$test2$1(Test.java:23)
at concurrent.lrucache.strongRefercence.Test$$Lambda$1/159413332.load(Unknown Source)
at concurrent.lrucache.strongRefercence.LRUCache.get(LRUCache.java:51)
at concurrent.lrucache.strongRefercence.Test.test2(Test.java:25)
at concurrent.lrucache.strongRefercence.Test.main(Test.java:8)
强引用产生了内存溢出问题。
我的应用程序中的多个 Activity 在 ListView 中显示图像,其中 ListView 的每一行都包含一个 ImageView. 这方面的一个示例是用户搜索、获取结果并显示每个结果的图片的搜
一 点睛 强引用(Strong Reference)是我们使用最多的一种对象引用,当一个对象被关键字 new 实例化出来的时候, JVM 会在堆(heap)内存中开辟一个内存区域,用于存放与该实例对应
我使用了代码 android lrucache example (Memory Cache)缓存下载的图像(总共将近 120 KB)并且它可以工作,但是当我从 Activity (或应用程序)中退出时
我正在阅读这篇文章来了解 Java 中的 LRUCache - Java LRU cache using LinkedList 这篇文章中有一个解决方案: public class LRUCache
我正在考虑为 Android 实现离线模式,但为了实现这一目标,我需要实现一个缓存系统。我读到人们建议 LruCache 并在这里看到了图像的示例 LruCache Example 。现在我不缓存图像
我正在尝试遵循有关 LruCache 使用的 2 年历史的 android 教程,到目前为止我在 Google 上搜索的一些示例具有相同的方法,即传递一个转换为 KiB 的值(int)。 final
我不能完全理解 LruCache 的内存管理组件。 从某种意义上说,我希望它能充当 iOS 平台上的 NSCache(最近刚刚从该操作系统中学到了一些知识)。 如果应用程序内存不足,LruCache
以下示例表明,在 LRUCache 之外分配新空间时,使用有限大小的 LRUCache 会导致 OutOfMemory 错误。 属性:64MB 进程大小; 10MB LRUCache 大小;我循环放入
我正在使用 LruCache 来缓存我的应用程序中使用的大量小 BitmapDrawables。问题是尺寸因我使用图像的不同位置而异。 我在从缓存中检索可绘制对象时设置边界,然后再将其设置为 Imag
我是 android 中 LruCache 的新手,我想在此缓存上放置和获取位图图像 (JPEG) 以防止内存错误和内存异常,所以我不明白为什么我的代码不起作用。这是我的代码: ImageView i
我已经在 Android 中实现了一个存储对象的标准 LRUCache。每个键都是与存储的对象关联的唯一 ObjectId。我的问题是从缓存中检索对象的唯一方法是通过 ObjectId(无迭代器)。实
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); final int cacheSize = max
例如对 网络加载图片进行缓存 : ? 1
我尝试解决 LeetCode 中的问题,要求实现一个LRUCache。当我提交代码时,系统告诉我结果是错误答案。 由于测试用例太长,我在代码中找不到问题。当我选择“运行代码”来提交我的代码时,它是正确
我可以在 Cachetools 的 LRUCache 实现中使用多个/组合键吗?我想像下面这样使用它 def fun(a,b): pass x = LRUCache(maxsize=100,missi
我有一个 LRUCache,用于缓存缩略图和其他类似的小位图。目前,我在我的主要 Activity 中使用它,但是,我也想在我的其他 Activity 中使用它。这让我想知道将这个 LRUCache
我从 developer.android.com 上读到了关于使用 LruCache 的信息,我从一个 Activity 中创建了一个模糊的 Bitmap 并将其放入缓存中,现在我想访问来自另一个 A
我一直在尝试在我的应用程序中实现 LruCache,但我在连接点和在不同组件之间传递位图时遇到困难。 我想知道如何在我的应用程序中集成 LruCache。我也想了解实现 LruCache 的过程,所以
我正在尝试在 android 中使用 LruCache 来缓存一些图像,但它没有缓存 这是代码 int cacheSize1 = 4 * 1024 * 1024; // 4MiB bit
我有以下代码来缓存位图,当我尝试使用它们的键检索它们时。他们总是返回 null 。请帮我 。谢谢你 final int memClass = ((ActivityManager) mcontext.
我是一名优秀的程序员,十分优秀!