gpt4 book ai didi

java - 如果 SoftReference 的引用已被 GC,如何对其进行 GC

转载 作者:行者123 更新时间:2023-12-01 15:15:31 27 4
gpt4 key购买 nike

我有一个

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

并且希望当 SoftReference 的引用被 GC 时从映射中删除键/值对。

我该如何实现这一目标?

最佳答案

当 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

如图所示,当引用被 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();
}

}

然后分别用SoftReferenceMonitor和CustomizedSoftReference替换SoftReference和SoftReferenceMonitor,并运行程序。结果是:

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。

希望这有用。

关于java - 如果 SoftReference 的引用已被 GC,如何对其进行 GC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11661227/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com