我想实现一些可重用的对象池。此外,我不想让API在不需要时将对象放回池中。
我想使用垃圾收集器通知我它将删除该对象,因为它没有引用,因此我可以阻止对象被垃圾收集并将其放回池中。
答案 0 :(得分:1)
我认为你不会得到一个令人满意的答案,它会神奇地返回未使用的对象,否则每个人都会这样做。 Java有一个ReferenceQueue,垃圾收集对象放在其上,但即便如此,我也不建议根据GC行为。
如果您想避免必须从池中显式释放对象,您是否考虑过使用回调/委托功能? API将接受将提供对象的委托,并且应用程序可以使用委托中的对象。完成后,保证清理。 (编辑:我的意思是保证返回游泳池)。
class Pool
{
public delegate void UseResource(Object object);
public void GetObject(UseResource del)
{
Object o = null;
try {
o = getFromPool();
del(o)
} finally {
if (o != null) returnToPool(o);
}
}
}
答案 1 :(得分:0)
为什么不保留对该对象的引用,以便它不会被标记为gc?
回答您关于GC如何知道它不再使用的问题:
垃圾收集的一种方法是保持引用计数。当引用计数达到0时,不再引用该对象,并且可以是Garbage Collected。 这不是.NET实现它的方式(参见Garbage Collection),但它可能有助于更好地理解原理。
编辑: 我是如何理解的,你需要一个曾经实例化的对象池,你可以只分发和收集它们。基本上,您希望在GC之上实现内存管理。
我可以看到想要这样做的唯一原因是创建对象的新实例并使其可用(初始化)需要花费太多时间。
无论如何,您可以尝试传统的非托管方法:
Stack pool = new Stack();
// Initialize a few MyObjects
pool.Push( new MyObject() );
// Get an instance of the object from the pool
MyObject obj = (MyObject)pool.Pop();
// Use the object
obj.Foo();
// When you are finished clean up
pool.Push(obj);
obj = null;
答案 2 :(得分:0)
如果你的Pool类只是你想要的对象列表,那么它们永远不会被垃圾收集,因为你总是引用池中的对象。
答案 3 :(得分:0)
你会发现这是相对不切实际的。没有办法让GC通知你即将销毁的对象。听起来你正试图管理自己的内存空间,这不是C#面向的任务。
不可否认,您可以使用池系统和引用计数来完成它,这样您就可以知道任何人何时没有引用您的对象。但是,这似乎非常危险。
答案 4 :(得分:0)
我认为理论上可以使用C#弱引用实现回收方案。
我们的想法是为托管对象构建代理,并在客户端从池请求对象时发出代理。该池包含对真实对象的硬引用和对代理对象的弱引用。 (并且代理有一个对真实对象的硬引用。)
当应用程序删除对代理对象的引用时,它(最终)将被垃圾收集,并且(甚至更晚)池中的弱引用将被破坏。稍后,池注意到弱引用保持为null,然后可以安全地发出新代理,创建一个新的弱引用并将其发布给应用程序。
在实践中,这真是个糟糕的主意。首先,对于GC来说,弱引用可能是昂贵的,并且可能需要多个GC周期才能破坏弱引用。并添加池和代理使用的空间,以及通过代理执行操作的性能成本。最有可能的是,这些成本的总和将大大超过使用对象池回收对象的任何好处。