通常,引用计数具有“它无法检测循环”的弱点。但是,在某些情况下,引用计数非常有用:
class EmergencyPatient {
DoctorPtr doctor;
EmergencyPatient() { doctor = Doctor::acquire(); }
~EmergencyPatient() { Doctor::release(doctor); }
};
现在,在引用计数世界中,一旦我们不再提及EmergencyPatient,医生就会被释放。
在Java的非refcounted世界中,这在很大程度上取决于EmergencyPatient何时被垃圾收集 - 并且由于垃圾收集器是世代的,所以EmergencyPatient可以是老一代,而不是很长时间收集。
解决此问题的正确方法是什么? (一旦我知道它们不再被使用,我想要释放一些资源。)
谢谢!
答案 0 :(得分:4)
在Java框架中解决此问题的正确方法是使用try-finally结构:
Doctor doctor = doctorFactory.acquire();
try
{
EmergencyPatient patient = new EmergencyPatient(doctor);
doctor.examinePatient();
}
finally
{
doctor.release();
}
顺便说一句,你会注意到,在我的实施中(就像在现实世界中一样!),病人不会去看医生。这使您能够在单元测试中为患者提供模拟医生。
编辑:远离制造类,这是您应该为每个java.sql.Connection
,每个java.io.InputStream
或任何其他管理非内存资源的对象使用的结构。
答案 1 :(得分:3)
您正在将分配资源(如在医生中)与分配内存混为一谈。如果它是你珍贵资源的内存,那么你是对的,Java并没有给你其他语言可能的细粒度控制。你没有获得细粒度控制的好处就是你可以从微观管理中解脱出来,这可以提高生产力和稳定性。
如果您正在管理内存以外的资源(例如,在这种情况下是医生),您可以使用其他模式来确保在使用它们的对象不再需要它们时释放它们。一种方法是让患者在接受治疗时锁定医生,然后在治疗后松开锁。
答案 2 :(得分:0)
垃圾收集管理内存资源。如果需要更多内存,GC将使其可用。如果你有其他类型的资源,文件句柄,数据库连接等,你可以管理那些你想要的生命周期。
答案 3 :(得分:0)
如果检查4个参考对象,当您的对象变为“符合垃圾回收条件”时,会有一个参考对象通知您。这意味着您不必等待“大”GC,如果您的对象无法访问,它可以在其中一个次要通道中通知您,即使它位于较老一代的区域之一。
我相信这应该是你正在尝试的正确方法。