Java 覆盖SoftReference的引用对象以保持数据活动是否存在任何问题?
因此,我正在编写从数据库中提取对象的代码。其中一些物体相当大。我需要一种方法来缓存它们。为此,我在Java 覆盖SoftReference的引用对象以保持数据活动是否存在任何问题?,java,caching,volatile,finalize,soft-references,Java,Caching,Volatile,Finalize,Soft References,因此,我正在编写从数据库中提取对象的代码。其中一些物体相当大。我需要一种方法来缓存它们。为此,我在SoftReference中引用持久对象 但是,在当前线程不知情的情况下,外力可能会作用于数据库并从数据库中删除此对象。我想做的是,如果发生这种情况并且收集了SoftReference,则可以降低丢失对象的风险 为此,我编写了以下代码 public class SoftDBObject { /** A hard reference to the wrapped persistable objec
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...
}
公共类SoftDBObject
{
/**对包装的持久对象的硬引用。当
*在数据库中持久化。这是空的*/
//我让它“不稳定”,但我不确定它是否需要。我想
//如果终结器线程需要设置此对象,则当前
//线程应立即通知。
受保护的挥发性瞬态O hardRef;
/**对包裹对象的软引用*/
专用瞬态软参考softRef;
/**唯一的ID号*/
保护瞬变长周期;
/**此类持有一个引用。在垃圾收集时,它会检查
*查看引用对象是否在数据库中是可持久的。如果不是,则
*将其包含的包装引用值传输到硬
*外部类中的引用。这可确保
*从数据库中删除,软引用将不会删除
*意外地拒绝*/
阶级持有者
{
最后O指代物;
公众持有人(最终参考)
{
this.referent=referent;
}
受保护的void finalize()抛出可丢弃的
{
super.finalize();
if(softRef!=null)
{
//如果对象不再在数据库中持久化,则传输
//外部类中硬引用的引用。
//否则,允许回收软引用,以及
//使用referent。我们只需要将值
//如果在数据库中需要对象,请从数据库中调用该对象
//未来。
最终O温度=刷新内部(纵向);
if(temp==null)
{
hardRef=参考物;
softRef=null;
}
}
}
}
/**此方法查询数据库,查找持久化对象,然后
*返回它。如果找不到对象,则返回null*/
私人O refreshInternal(最终长时间)
{
//这不重要。。。
返回(O)刷新对象;
}
//其他一些不重要的东西。。。
}
总而言之,当您最初从数据库中拉出对象时,它会被放置到支架
,这是软引用
的参照物<此时code>hardRef将为null
,并且long
值将用作“锚定”,以便在必要时从数据库中拉下对象
一旦内存紧张,可能会收集SoftReference
。但是,在此之前,我想检查对象是否仍然存在于数据库端。如果没有,那么我想将本地维护的对象转移到hardRef
,并将SoftReference
设置为null
如果对象仍然在数据库中,那么我们可以允许收集引用对象。下次我们需要回忆对象时,我们将使用longID去获取它。(请注意,如果发生这种情况后,有人删除了它,那么我可以抛出一个异常)
我问这个问题是因为每个人似乎都说finalize()是邪恶的,我不应该使用它。问题是,我看不到任何其他方法。
finalize()
会造成巨大的性能损失。如果你期望有成千上万的这样的物体,你一定要避开它。即使没有这一点,我也可能更喜欢使用引用队列参数创建软引用,并使用它来检测对象何时进入收集队列。问题是(至少据我所知),当SoftReference
到达ReferenceQueue
时,调用get()
将返回null。这意味着我将无法保存其中包含的数据。我认为只有PhantomReference
才能做到这一点。至少我在SoftReference
的文档中看不到任何说明get()
将返回null
的内容。为什么要在最后一分钟保留对没有其他引用的内容的引用?即使代码在技术上可行,这将是一个巨大而复杂的混乱局面,我将避免。如果一个包装在引用被丢弃之前没有被持久化,那么它就不应该被持久化finalize()
在引用进入队列之前被调用,这意味着您无法从ReferenceQueue
清理线程恢复引用对象。finalize()
会造成巨大的性能损失。如果你期望有成千上万的这样的物体,你一定要避开它。即使没有这一点,我也可能更喜欢使用引用队列参数创建软引用,并使用它来检测对象何时进入收集队列。问题是(至少据我所知),当SoftReference
到达ReferenceQueue
时,调用get()
将返回null。这意味着我将无法保存数据