Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
另一个强制Java垃圾收集问题(我认为这是一个合理的用例)_Java_Garbage Collection - Fatal编程技术网

另一个强制Java垃圾收集问题(我认为这是一个合理的用例)

另一个强制Java垃圾收集问题(我认为这是一个合理的用例),java,garbage-collection,Java,Garbage Collection,我有一个数据生成器,它生成的数据由许多不同的消费者使用(我们称之为Cs)。每个C都有自己感兴趣的数据集。数据生产者对Cs的引用较弱,因此可以通知他们进行更新 每个C也被许多独立的组件使用,因此没有一个组件可以告诉我们何时不再需要C,所以我们必须让JVM来确定C何时可以GC 这里的目标是在C过时时得到通知,以便数据生产者可以关闭只对未使用的C感兴趣的数据 正如我前面提到的,数据生产者总是对Cs有弱引用,所以当C是GCed时,很容易做到这一点。然而,我注意到,Cs通常在最终GC ed之前在VM中停留

我有一个数据生成器,它生成的数据由许多不同的消费者使用(我们称之为Cs)。每个C都有自己感兴趣的数据集。数据生产者对Cs的引用较弱,因此可以通知他们进行更新

每个C也被许多独立的组件使用,因此没有一个组件可以告诉我们何时不再需要C,所以我们必须让JVM来确定C何时可以GC

这里的目标是在C过时时得到通知,以便数据生产者可以关闭只对未使用的C感兴趣的数据

正如我前面提到的,数据生产者总是对Cs有弱引用,所以当C是GCed时,很容易做到这一点。然而,我注意到,Cs通常在最终GC ed之前在VM中停留很长一段时间,而在这段时间里,数据生产者产生了大量它应该需要的数据

我有没有办法强制对未使用的Cs进行GC?我希望答案是肯定的,但我希望答案是否定的,所以作为后续问题,是否有人对我如何(重新)设计它以使其更好/更有效有好的建议

谢谢

下面的一些答案提出了很多好的观点,特别是关于强制C用户订阅和取消订阅的建议。这很困难,因为:


C只是接口I的一种可能实现(接口I没有订阅要求),这是用户真正使用的接口。C实现是在运行时注入的,因此我们不能强制用户遵守C特定的要求。(哎哟?

使用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();
}
设置组件=。。。
公共无效订阅(C组件){
if(components.isEmpty())
启用订阅();
组件。添加(组件);
}
公共无效取消订阅(C部分){
组件。移除(组件);
if(components.isEmpty())
禁用订阅();
}

也许我们可以先澄清一下您的体系结构。你有:

  • 数据生产者(P)
  • 若干消费者(C)
  • “使用”消费者的许多组件
  • 我想知道的是——从组件到消费者的关系是什么?您所说的是,有多个组件使用单个使用者

    一般来说,如果系统中只有p和Cs,那么你可以让C去注册它自己,你就完成了(正如Peter在他的例子中所示)。但是,在这种情况下,许多组件都使用C。我想,在对您的体系结构了解有限的情况下,我建议您让组件在需要时向每个C注册和取消注册,并且在所有组件取消注册时,C可以从P中取消注册。

    通过调用

    System.gc()
    您建议VM对内存状况采取措施。我引用javadoc的话:

    当控件从方法调用返回时,Java虚拟机已尽最大努力从所有丢弃的对象中回收空间

    注意,这并不意味着它实际上已经执行了GC,它只是检查是否需要执行。实际上,我还没有看到VM忽略
    System.gc()
    调用


    通常你不必也不应该这样做。VM比您(和我)对内存子系统的行为有更好的理解。但是,在某些情况下,如果应用程序行为不常见,并且您知道需要内存,那么就可以这样做。

    您不能强制JVM进行垃圾收集,最好通过调用
    System.gc()
    来提出建议


    也许更好的解决方案是引入某种侦听器模式,让您的Cs向数据生成器注册/注销,独立组件向您的C注册。当从您的C注销时,它可以检查是否不再需要它,在这种情况下,它可以从数据生成器中注销。

    我只使用System.gc()

    在这篇相关文章中有一些非常有趣的信息:


    显然,许多IDE也使用它来评估可用堆的数量。我想没有理由我也不能这么做。

    谢谢。问题是,Cs是一个现有的类,它被无数不同的目的使用,现在要求所有用户在使用它之前订阅它是不切实际的。此外,我们也无法强制C用户在使用C后会体面地取消订阅,这可能会导致严重的内存和资源泄漏。@RAY:如果您不能确保C用户正确关闭它,您如何确保他们会放弃对C的任何引用?如果您有不可靠、无法维护的代码,效率不应该是一个考虑因素,你只需要按照有效的方法去做,并希望做到最好。@Joachim Sauer这是公平的观点。我想区别在于,如果用户要明确地做到这一点,我们会要求他们更加勤奋。机会是(就像我的例子一样),这些用户不会长寿,当他们自己死后,C的引用就被释放了。C的实现试图适应更通用的范例。假设它实现了一些接口I,只是众多实现中的一个。C的用户实际上是I的用户,因此要求他们了解C特定的需求是可行的(或正确的?),谢谢。我想这和彼得·劳里的建议是一样的。Cs是由不需要对C类有深入了解的人/程序使用的,因此很难强迫他们注册