所以我正在编写从数据库中提取对象的代码。其中一些对象非常大。我需要一种方法来缓存它们。为此,我引用SoftReference
中的持久对象。
但是,外部力量可以对数据库起作用,并且在没有当前线程知识的情况下从数据库中删除该对象。我想要做的是降低丢失对象的风险,如果发生这种情况并收集SoftReference
。
为此,我编写了这段代码
public class SoftDBObject
{
/** A hard reference to the wrapped persistable object. When the object
* is persisted in the database. this is null. */
// I made this "volatile", but I'm not sure if it needs to be. I figure
// if the finalizer thread needs to set this object, then the current
// thread should be made aware immediately.
protected volatile transient O hardRef;
/** A soft reference to the wrapped object. */
private transient SoftReference<Holder> softRef;
/** The unique ID number. */
protected transient long longID;
/** This class holds a referent. Upon garbage collection, it checks to
* see if the referent persistable is in the database. If not, then it
* transfers the wrapped referent value it contains to the hard
* reference in the outer class. This ensures that if an object is
* deleted from the database, the soft reference will not drop the
* object unexpectedly. */
class Holder
{
final O referent;
public Holder(final O referent)
{
this.referent=referent;
}
protected void finalize() throws Throwable
{
super.finalize();
if(softRef!=null)
{
// If the object is no longer persisted in the database, transfer
// the referent to a hard reference in the outer class.
// Otherwise, allow the soft reference to be reclaimed, along
// with the referent. We will only need to longID value to
// recall the object from the database if we need it in the
// future.
final O temp=refreshInternal(longID);
if(temp==null)
{
hardRef=referent;
softRef=null;
}
}
}
}
/** This method queries the database, finds the persisted object, and
* returns it. If the object was not found, then it returns null. */
private O refreshInternal(final long longID)
{
// it's not important...
return (O)refreshedObject;
}
// Some other non-important stuff...
}
总而言之,当您最初从数据库中下拉对象时,会将其放入Holder
,这是SoftReference
的指示对象。此时hardRef
为null
,long
值将用作“锚点”,以便在必要时从数据库中下拉对象。
一旦内存变紧,可能会收集SoftReference
。但是,在它之前,我想检查对象是否仍然存在于数据库端。如果没有,那么我想将本地维护的对象转移到hardRef
并将SoftReference
设置为null
。
如果对象IS仍在数据库中,那么我们可以允许收集引用对象。下次我们需要调用该对象时,我们将使用longID来获取它。 (请注意,如果发生这种情况后,有人将其删除,那么我可以抛出异常)。
这会有用吗?换句话说,我可以期望Holder.referent为非null并且能够在没有任何数据竞争的情况下将hardRef设置为该值吗?
我是否希望看到任何重大的表现?我知道敲定有一些头脑,但只要我不把事情搞砸,我想我们没事。
我问这个问题,因为每个人似乎都认为finalize()是邪恶的,我永远不应该使用它。问题是,我只是看不到任何其他方式。