2

クラスのコンストラクターでは、現在のオブジェクト(this)とそのキー(コンストラクターにパラメーターとして入力された文字列)を静的なLinkedHashMapにマップし、後で必要になる可能性のある場所で文字列によってオブジェクトを参照できるようにします。 。

コードは次のとおりです(役立つ場合):

public class DataEntry {
    /** Internal global list of DataEntry objects. */
    private static LinkedHashMap _INTERNAL_LIST;

    /** The data entry's name. */
    private String NAME;

    /** The value this data entry represents. */
    private Object VALUE;


    /** Defines a DataEntry object with a name and a value. */
    public DataEntry( String name, Object value )
    {
        if( _INTERNAL_LIST == null )
        {
            _INTERNAL_LIST = new LinkedHashMap();
        }

        _INTERNAL_LIST.put( name, this );

        NAME = name;
        VALUE = value;
    }
}

問題?このクラスのインスタンスは、使い終わってもガベージコレクションされません。

このクラスのインスタンスを使い終わったときに、毎回手動でRemove()メソッドなどを呼び出さなくても、このクラスのインスタンスをクリーンアップする方法があるかどうか知りたいです(内部のLinkedHashMapでその参照を削除するために)私はもうそれらを使用していません、つまり)。

4

3 に答える 3

6

代わりに値をWeakReferences (またはSoftReferences ) にします。そうすれば、値をガベージ コレクションすることができます。もちろん、マップにはまだエントリがありますが、Weak/SoftReference が空になったエントリのマップを定期的にクリアできます。

于 2008-12-06T21:09:41.640 に答える
5

コンストラクターが完了する前にオブジェクトを他のユーザーから見えるようにすることは、スレッド セーフではありません。

この場合、マップがどのように使用されているかは明確ではありませんが、クラスに次のような静的メソッドがあるとします。

public static DataEntry getEntry(String name) {
  return _INTERNAL_LIST.get(name);
}

同時に実行されている別のスレッドDataEntryは、作成中に にアクセスし、初期化されていない を持つエントリの使用を開始できますVALUE。コンストラクターでコードを並べ替えて、新しいインスタンスをマップに追加するのが最後になるようにしても、JVM は命令を並べ替えて、オブジェクトが最初にリストに追加されるようにすることができます。または、クラスが拡張されている場合は、オブジェクトが発行された後にサブクラスの初期化が行われる可能性があります。

複数のスレッドがDataEntryクラスとの対話にアクセスする場合、プラットフォームに依存し、断続的で、診断が非常に難しい同時実行バグが発生する可能性があります。

Brian Goetz による記事「安全な建設」には、このトピックに関する詳細が記載されています。

元の質問に戻る:WeakReference他の人が述べたように、を使用することは良いアプローチですが、マップ内のすべてのエントリを反復するのではなく、拡張する値のラッパーを作成することをお勧めしますWeakReference(それはあなたDataEntry自身、またはhelper)、各参照をReferenceQueue. こうすることで、収集されたエントリのキューをすばやくポーリングし、それらをマップから削除できます。これは、クラス初期化子で開始されたバックグラウンド スレッド ( でブロックremove) によって実行できます。または、新しいエントリが追加されるたびに古いエントリを (ポーリングによって) 消去することもできます。

プログラムがマルチスレッドの場合、LinkedHashMapからのマップを放棄するjava.util.concurrentか、 でラップするLinkedHashMap必要がありCollections.synchronizedMap()ます。

于 2008-12-06T22:06:21.243 に答える
1

あなたが使いたいのは弱参照のようです。コンセプトは、弱参照は、オブジェクトが GC されないようにするほど強力ではないということです。私はそれらについてあまり経験がありませんが、ここで詳細を学ぶことができます。

于 2008-12-06T21:03:37.423 に答える