我有一个方法可以创建一些重型对象作为缓存。这些对象很少被访问,但是昂贵且处理速度很慢,并且仅按按需进行初始化。然后在使用我的应用程序时,例如,我可以请求大约三个这样的重物,然后重复使用它们,但也有可能我运行一次它只占用内存,而我在会话期间再也不会使用它。
我的问题是:我可以定义一个对象是" 垃圾收集",如果应用程序需要更多内存,它会取消设置这些未使用的数据?
我认为它应该像那样(伪代码):
private static MyInstance instance = null;
public static getInstance() {
if (instance == null) {
instance = calculate();
GC.put(instance);
}
return instance;
}
我认为我可以用某种Timer来做,然后不时检查,但我想Java应该有这样的东西,只有在内存占用很多的情况下才能调用。
答案 0 :(得分:1)
Java无法手动取消分配内存(请参阅Memory Management in Java。但是,它确实有自动垃圾回收。这意味着任何没有引用的对象都会留在程序将被自动删除。例如,在你的情况下,如果不再使用Instance
(使用它的函数返回,并且不存在其他引用,或者你覆盖存储引用的唯一变量<{1}}还有其他东西),Instance
将被垃圾收集。
不,但是,使Instance
消失的任何方法都比删除对它的引用更快,并让垃圾收集器处理它。
对于您的应用程序,我建议使用LRU缓存(请参阅How would you implement an LRU cache in Java?),这会将您的内存使用限制为数量实例,(取决于Instance
究竟是什么)会将您限制为Instance
使用的设定内存量。
如果您希望允许使用任意数量的内存,但不用于很长时间,您可以为Instance
创建一个包装类,它实现了您的缓存创意(只有在调用时才会创建Instance
,如果其当前副本为Instance
),但会保留计时器并在给定时间过期后将其null
设置为Instance
它被使用了。
答案 1 :(得分:1)
您需要的是适当的缓存实施。 Java中有很多它们,例如Guava Cache,它是高度可配置的。
您的calculate
方法只是CacheLoader#load。
您不需要关心GC。只需正确调整缓存大小,以免使用太多内存。自动收集被驱逐的缓存条目(未在别处引用时)。
我认为我可以用某种Timer来做,然后不时检查,但我想Java应该有这样的东西,只有在内存占用很多的情况下才能调用。
你可以使用基于时间的驱逐CacheBuilder#expireAfterWrite
。 Java本身没有缓存,但有SoftReference。无论如何,我不建议直接使用它,但考虑将其与CacheBuilder#softKeys
一起使用。
答案 2 :(得分:1)
是的,Java提供了对内存使用敏感的three types of indirect references。
缓存可以使用在进程引发OutOfMemoryError
之前将被清除的SoftReference
。但是,只要有足够的内存,SoftReference
就会阻止它的引用被垃圾收集。