我有一个数据生成器,它生成许多不同消费者使用的数据(我们称之为Cs)。每个C都有自己感兴趣的数据集。数据生成器对Cs的引用很弱,因此可以通知他们更新。
每个C也被许多独立组件使用,因此没有一个组件可以分辨何时不再需要C,所以我们必须将它留给JVM以确定何时C是GC能够的。
此处的目标是在C变得过时时收到通知,因此数据生产者可以关闭仅对未使用的C感兴趣的数据。
正如我前面提到的,数据生成器总是对Cs的引用很弱,所以当C是GC时很容易做到。但是,我注意到Cs通常会在VM最终GC-ed之前长时间停留在VM中,而这一切,数据生产者正在产生它应该需要的大量数据。
有没有办法强制GC使用未使用过的Cs?我希望是的,但是我期待一个No,所以作为一个后续问题,是否有人对我如何(重新)设计这个以使其更好/更有效地工作有一个很好的建议?
谢谢!
下面的一些答案提出了很多好处 - 尤其是强制用户C订阅和取消订阅的建议。这很难,因为:
C只是接口I的一种可能实现(没有此订阅要求),这是用户真正使用的。 C实现是在运行时注入的,因此我们不能强制用户遵守C特定的要求。 (哎哟?)
答案 0 :(得分:2)
使用C的组件可以在他们感兴趣并且不再感兴趣时通知。
如果至少有一个感兴趣的组件,请启用订阅。 (此处不会出现此情况),当最后一个组件取消订阅时,请关闭数据。
Set<C> components = ...
public void subscribesTo(C component) {
if (components.isEmpty())
enableSubscription();
components.add(component);
}
public void unsubscribeFrom(C component) {
components.remove(component);
if (components.isEmpty())
disableSubscription();
}
答案 1 :(得分:1)
我将使用System.gc();
这篇相关文章中有一些非常有趣的信息: Java: How do you really force a GC using JVMTI's ForceGargabeCollection?
显然,许多IDE也使用它来评估可用堆的数量。猜猜我没有理由不这样做。
答案 2 :(得分:0)
也许我们可以先澄清您的架构。你有:
我想知道的是 - 从组件到消费者的关系是什么?您所说的只是有多个组件使用单个消费者。
一般来说,如果系统中只有P和Cs,那么你就可以让C取消自我注册并完成(正如彼得在他的例子中所示)。但是,在这种情况下,许多组件都使用C.我猜你的架构知识有限,我建议你在需要的时候让每个C注册和取消注册组件,C可以取消注册当所有组件取消注册时,它本身来自P.
答案 3 :(得分:0)
通过调用System.gc()
你建议到VM,它应该对内存情况做些什么。我引用了javadoc:
当控制从方法调用返回时,Java虚拟机已尽最大努力从所有丢弃的对象中回收空间。
请注意,这并不意味着它实际上已经执行了GC,它只是检查它是否需要。在实践中,我还没有看到VM忽略System.gc()
调用。
通常你不必也不应该这样做。与您(和我)相比,VM对内存子系统的行为有了更好的理解。但是,在某些情况下,如果应用程序行为不常见且您知道需要内存,则可以这样做。
答案 4 :(得分:0)
您无法强制JVM进行垃圾回收,您可以通过调用System.gc()
来建议它。
也许一个更好的解决方案是引入某种类型的Listener模式,你的Cs注册/注销数据生成器和注册你的C的独立组件。当你从C注销时,它可以检查它是否为no需要更长时间,在这种情况下,它可以从数据生产者注销。