Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果软引用是GC',如何对其进行GC;预计起飞时间_Java - Fatal编程技术网

Java 如果软引用是GC',如何对其进行GC;预计起飞时间

Java 如果软引用是GC',如何对其进行GC;预计起飞时间,java,Java,我有一个 ConcurrentMap<String, SoftReference<X>> map = new ConcurrentHashMap<String, SoftReference<X>>(); ConcurrentMap=new ConcurrentHashMap(); 并且希望在对SoftReference的referent进行GC’ed时从映射中删除键/值对 我怎样才能做到这一点呢?你考虑过吗 它将为您处理这方面的问题 如果您真的

我有一个

ConcurrentMap<String, SoftReference<X>> map = new ConcurrentHashMap<String, SoftReference<X>>();
ConcurrentMap=new ConcurrentHashMap();
并且希望在对SoftReference的referent进行GC’ed时从映射中删除键/值对

我怎样才能做到这一点呢?

你考虑过吗

它将为您处理这方面的问题


如果您真的不能使用这个库,那么您可能必须重写concurrentHashMap来测试softreference是否仍然保留某些内容,并删除该条目。在这种情况下,当softreference的引用被GC’ed时,

键/值对将不会被删除。 下面的程序显示了结果

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;
    }

}
如图所示,当引用被GC'ed时,不会删除键/值对

您可以实现自己的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();
    }

} 
现在,键/值对已被删除

此外,您还可以使用另一个线程来构造SoftReferenceMonitor实例并监视SoftReference


希望这有用。

SoftReference
映射中的对象将不会被垃圾收集,除非您将其从映射中删除,并且没有引用指向该对象。首先从映射中删除
对,然后它将被自动垃圾收集


使用

您这样做是为了测试还是为了生产代码?如果要进行测试,可以考虑强制内存不足,或者在JVM上配置SoftRefLRUPolicyMSPerMB。希望对生产有所帮助,这是一个缓存。但是,我没有添加JVM参数的选项。我想可能有一些方法可以通过引用队列实现这一点,但我不确定具体如何实现。我知道,我需要知道何时删除这对。谢谢,我最终使用了类似的解决方案。
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();
    }

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