0

私は

ConcurrentMap<String, SoftReference<X>> map = new ConcurrentHashMap<String, SoftReference<X>>();

SoftReferenceの指示対象がGCされたときに、キーと値のペアをマップから削除する必要があります。

これを達成するにはどうすればよいですか?

4

3 に答える 3

1

SoftReference の指示対象が GC されている場合、キーと値のペアは削除されません。次のプログラムは結果を示しています。

package test.gc;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

public class TestSoftReference {

    public static ReferenceQueue<TestModel> referenceQueue = new ReferenceQueue<>();
    public static ConcurrentHashMap<Integer, SoftReference<TestModel>> map = new ConcurrentHashMap<>();

    public static void main(String[] args) throws InterruptedException {
        final int KEY1 = 1;

        TestModel testModel1 = new TestModel(KEY1);
        SoftReference<TestModel> reference1 = new SoftReference<TestModel>(testModel1, referenceQueue);

        map.put(testModel1.getNumber(), reference1);

        testModel1 = null;

        while (true) {  
            Object obj = referenceQueue.poll();  
            if (obj != null) {  
                System.out.println("queue.poll at " + new Date() + " " + obj);
                break;  
            }  
            System.gc();  
        }  

        SoftReference<TestModel> tempReference = null;
        tempReference = map.get(KEY1);
        System.err.println("reference:" + tempReference);
        if (tempReference != null) {
            System.err.println("referent:" + tempReference.get());
        }
    }

}

class TestModel {

    private int number = 0;
    private int[] bigArray = null;

    public int getNumber() {
        return number;
    }

    public TestModel(int n) {
        if (n <= 0) {
            throw new IllegalArgumentException("argument n must greater than 0.");
        } else {
            number = n;
            bigArray = new int[n * 1024 * 1024];
        }
    } 

    @Override
    public String toString() {
        return "field bigArray's baseNumber is " + number + " and bigArray's length is " + bigArray.length;
    }

}

結果は次のとおりです。

    queue.poll at Thu Jul 26 14:37:21 CST 2012 java.lang.ref.SoftReference@1c501f7
    reference:java.lang.ref.SoftReference@1c501f7
    referent:null

示されているように、revent が GC された場合、キーと値のペアは削除されません。

独自の RefenceQueue と SoftReference を実装してターゲットを達成し、次のように独自のジョブを実行できる RefenceQueue の poll メソッドをオーバーライドできます。

class SoftReferenceMonitor extends ReferenceQueue<TestModel> {

    @Override
    public Reference<? extends TestModel> poll() {
        @SuppressWarnings("unchecked")
        Reference<TestModel> ref = (Reference<TestModel>) super.poll();
        if (ref != null) {
            int id = ((CustomizedSoftReference)ref).getId();
            TestSoftReference.map.remove(id);
            System.err.println("remove key/value '" + id + "' from map.");
        }
        return ref;
    }

}

class CustomizedSoftReference extends SoftReference<TestModel> {

    private int id;

    public int getId() {
        return id;
    }

    public CustomizedSoftReference(TestModel referent, ReferenceQueue<? super TestModel> q) {
        super(referent, q);
        this.id = referent.getNumber();
    }

} 

次に、SoftReference と SoftReferenceMonitor をそれぞれ SoftReferenceMonitor と CustomizedSoftReference に置き換えて、プログラムを実行します。結果は次のとおりです。

remove key/value '1' from map.
reference:null
queue.poll at Thu Jul 26 14:46:54 CST 2012 test.gc.CustomizedSoftReference@4e7958

これで、キーと値のペアが削除されました。

また、別のスレッドを使用して SoftReferenceMonitor インスタンスを構築し、SoftReference を監視することもできます。

これが役に立つことを願っています。

于 2012-07-26T06:57:42.103 に答える
0

グアバキャッシュを検討しましたか?

この側面を処理します。

このライブラリを本当に使用できない場合は、concurrentHashMap をオーバーライドして、ソフト参照がまだ何かを保持しているかどうかをテストし、その場合はエントリを削除する必要があります。

于 2012-07-26T06:45:42.490 に答える
0

SoftReferenceMap からのオブジェクトは、マップから削除し、参照がそのオブジェクトを指していない限り、ガベージ コレクションされません。最初<K,V>にマップからペアを削除すると、自動的にガベージ コレクションが行われます。

ConcurrentMap.remove()を使用する

于 2012-07-26T07:06:15.960 に答える