3

私はWeakHashMapを使ってある種のキャッシュを作ろうとしている別の人だと思います。そして、私はそれについていくらかの助けが必要です。

TrackDataオーディオトラックに関する情報を含むオブジェクトがたくさんあります。次に、内部Trackを参照し続けるオブジェクトがあります。TrackData複数のトラックが同じを指すことができますTrackData。次にTrackDataCache、次のようなクラスがあります。

public class TrackDataCache {
private static TrackDataCache instance = new TrackDataCache();

public static TrackDataCache getInstance() {
    return instance;
}

private WeakHashMap<TrackData, WeakReference<TrackData>> cache = new WeakHashMap<TrackData, WeakReference<TrackData>>();

public void cache(Track track) {
    TrackData key = track.getTrackData();
    WeakReference<TrackData> trackData = cache.get(key);
    if (trackData == null) {
        cache.put(key, new WeakReference<TrackData>(key));
    } else {
        track.setTrackData(trackData.get());
    }
}
}

したがって、トラックをロードするときに呼び出しTrackDataCache.cache()、そのトラックデータが以前にロードされていない場合は、キャッシュされるか、キャッシュされたコピーに置き換えられます(TrackDataequals()メソッドをオーバーライドして場所とサブソングインデックスを確認します)。トラックを削除するときに気にする必要がないように、弱参照を使用したいと思います。

WeakHashMapでキーへの弱参照を保持するのは大丈夫かどうかを尋ねたかったのですが、そうでない場合は、この問題にどのように対処すればよいですか?弱参照とキャッシュされた値の一定時間の取得が必要です。私はWeakHashMapコードをコピーしてgetEntry()メソッドを公開することを考えていました。これで問題は解決しますが、それは非常に悪いハックです:(

PS。apacheまたはgoogleコレクションのいずれかにこのようなものがあることは理解していますが、2Mbの依存関係を追加したくありません。

4

2 に答える 2

2

と交換WeakReferencesすることをお勧めしSoftReferencesます。

によってのみ参照されるオブジェクトWeakReferenceは、ガベージ コレクターのすべてのラウンドのターゲットです。これは、空きメモリがまだ十分にある場合でも、キャッシュをクリアできることを意味します。

置き換える場合はWeakReferenceSoftReference次のように述べます。割り当てる空きメモリがまったくない場合にのみ、参照されたオブジェクトを削除します。

Javaにはすぐに使用できるSoftHashMap実装はありません。guava- に良い例がありMapMakerます。この十分にテストされ、実稼働環境で検証されたコードを使用することは価値があり、品質が明らかに劣る独自の実装を提供することはありません。また、「セルフクリーニング」の驚くべきメカニズムもあります。

  1. キャッシュの最大サイズを指定できます:

    マップのサイズが最大値に近づくと、マップは、再度使用される可能性が低いエントリを削除します。たとえば、マップは、最近または頻繁に使用されていないエントリを削除する場合があります。

  2. expireAfterWriteおよびexpireAfterAccessメソッドを使用して、マップ エントリの有効期限を指定できます。

また、キャッシュの設計があまり便利ではないと思います。あなたのコード スニペットからわかるように、最初からあなたTrackの s にはそれらへの強い参照がTrackDataあり、これらの状況に基づいてキャッシュを構築します。しかし、ある瞬間から、キャッシュを使用してデータを取得したいTrackので、別の方法で新しい を作成する必要があります。その瞬間から、キャッシュを使用したいが強い参照はしたくないからです。

異なるTracksものは同じものを持つことができるので、キーとしてTrackData使用することはできません。Trackしたがって、次のアプローチを使用します。

  1. 中間 ID レベルを導入しMap<Integer, TrackData>、ソフト値と定義されたセルフクリーニング戦略 (に基づくMapMaker) に基づいてキャッシュを作成します。
  2. Track --> TrackDataへの変更関係Track --> Id (int)。キャッシュId --> TrackData
于 2010-12-05T09:51:20.347 に答える
1

TrackDataの多くのインスタンスで共有できますTrackTrackData同じインスタンスを複数取得する必要のないキー システムが必要ですTrack

 public class Track [

   @Override
   public int hashcode() {
     ... make hashcode that will be the same for
     ... tracks sharing the same track data.
   }

   @Override
   public boolean equals() {
     ... ensure that if A.hashcode == B.hashcode then A.equals(B)
   }

 }

 public class TrackDataManager {

   private WeakHashMap<Track,TrackData> cache = new WeakHashMap<Track,TrackData>();

   public TrackData getTrackData(Track track) {

     // Track.hashcode()/equals() ensures two tracks that
     // share track data will get the same object back
     TrackData data = cache.get(track);

     if (data == null) {

       data = constructDataFromTrackFile(track);

       cache.put(track, data);

     }

     return data;

   }

   private TrackData constructDataFromTrackFile(Track track) {
     ... read data from file and create that object.
   }

 }

オブジェクトの構築TrackDataが常にファイルの読み取りの一部として行われるが、作成されたインスタンスが共有インスタンスのために破棄される場合、次のようにモデル化します。

 public class TrackData {

   @Override
   public int hashcode() {
     ... make hashcode that will be the same for same track data.
   }

   @Override
   public boolean equals() {
     ... ensure that if A.hashcode == B.hashcode then A.equals(B)
   }

 }

 public class TrackDataCache {

   private WeakHashMap<Integer,TrackData> cache = new WeakHashMap<Integer,TrackData>();

   public TrackData getTrackData(Track track) {

     // cache contains shared TrackData instances, we may throw away
     // the Track instance in favour of the shared one.

     Integer key = track.getTrackData().hashcode();

     TrackData data = cache.get(key);

     if (data == null) {

       cache.put(key, track.getTrackData());
       data = track.getTrackData();

     } else {

       // ensure we're using the shared instance, not the local one.
       // deliberate object reference comparison  
       if (data != track.getTrackData()) {
         track.setTrackData(data);
       } 

     }

     return data;

   }

 }

への参照を保持しているオブジェクトが生きているWeakHashMap限り、 は 2 つのソリューションのいずれにおいても何もしないことに注意してください。これは内部を作成することで修正できますが、それはまた、 が何もないことになり、ファイルから読み戻す必要があることを意味します。この場合、最初のソリューションは 2 番目のソリューションよりもモデル化されています。TrackTrackDataWeakReferenceTrackTrackData

于 2010-12-04T18:30:02.343 に答える