4

私はグアバキャッシュで奇妙な(少なくとも私にとっては)振る舞いをしています。最初のヒットの後、次のアクセスは空のオブジェクトを返します。私は奇妙な証拠を使用しなかったので、どこが間違っているのか理解できません。次のLoadingCacheを宣言しました。

LoadingCache<String, Vector<Location>> locations = CacheBuilder.newBuilder()
            .maximumSize(100000)
            .build(
                    new CacheLoader<String,Vector<Location>>() {
                        @Override
                        public Vector<Location> load(String key)  {
                            return _getLocationListByTranscriptId(key);
                        }
                    });

そして私はこの方法でのみそれを使用しました:

public Vector<Location> getLocationListByTranscriptId (String transcriptid) {
    if (transcriptid.equals("TCONS_00000046"))  System.out.println("tcons found, will this work?");
    Vector<Location> result;
    try {
        result = locations.get(transcriptid);
    } catch (ExecutionException e) {
        System.err.println("Error accessing cache, doing the hard way");
        result = _getLocationListByTranscriptId(transcriptid);
    }
    if (transcriptid.equals("TCONS_00000046")){
        if (result.size()==0){
            System.out.println("this is a problem");
            return null;
        }
        System.out.println("this is good!");
    }
    return result;
}

入力文字列のコレクションを繰り返すと、次の出力が得られます。

tcons found, will this work?
this is good!
tcons found, will this work?
this is a problem

したがって、初めてキャッシュを使用するときは機能しますが、A)将来のアクセスのために値が正しく保存されません。B)奇妙な動作のために、値がリセットされます。私に何ができる?これを読んでくれてありがとう!

編集:axtavtの回答のおかげで、結果のリストをどこで編集しているかをすぐに把握できました。理由はわかりませんが、グアバキャッシュが値のコピーを返すことを確信していました。答えをありがとう、そして防御的なプログラミングについての提案をありがとう。(私がまだあなたの答えを評価できない場合は申し訳ありません)。

4

1 に答える 1

7

Vectorコードのどこかを誤ってクリアしたと思います。2つの可能性があります:

  • Vectorキャッシュから取得するコードによって変更されます。

    この種の間違いは、防御的なコピーを作成するか(キャッシュの概念を台無しにしますが)、コレクションの不変のビューを返すことで防ぐことができます。

    LoadingCache<String, List<Location>> locations = CacheBuilder.newBuilder()
         .maximumSize(100000)
         .build(
                 new CacheLoader<String, List<Location>>() {
                     @Override
                     public List<Location> load(String key)  {
                         return Collections.unmodifiableList(
                             _getLocationListByTranscriptId(key));
                     }
                 }); 
    

    このようにコードを変更すると、コレクションの違法な変更が行われている場所を簡単に見つけることができます。

    の変更不可能なビューはないVectorため、List代わりに使用する必要があることに注意してください。

  • _getLocationListByTranscriptId()結果を、他のメソッド(または同じメソッドの他の呼び出し)からアクセスできるフィールドに格納します。_getLocationListByTranscriptId()したがって、フィールドに結果への参照が残らないことを確認する必要があります。

于 2012-04-24T13:37:55.210 に答える