java - 弱引用和线程
问题描述
我试图了解如何WeakReference
工作以及为什么下面的代码片段会永远运行,即为什么dummy
字符串永远不会被 GC,尽管似乎删除了对它的所有引用?
import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) {
String dummy = new String("sdfsdfsdf");
WeakReference<String> dummyRef = new WeakReference<>(dummy);
Thread test = new Thread(
() -> {
while (true) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
String s = dummyRef.get();
if (s == null) {
System.out.println("String GC'd. Quitting.");
break;
}
System.out.println(s);
s = null;
}
}
);
test.start();
try {
dummy = null;
TimeUnit.SECONDS.sleep(30);
} catch (InterruptedException e) {
}
}
}
GC 是真的在这里运行,还是 lambda 持有对周围堆栈帧中对象的引用,尽管从未实际dummy
直接使用该变量?我必须进行哪些更改才能使代码按预期工作?
这个用例是一个类的工厂方法,它将产生一个线程,该线程定期调用返回对象的方法。如果创建的对象被销毁(即允许对象被 GC),我希望线程退出。
解决方案
如果包含激活垃圾收集器的原因,您的测试应该可以工作。让我们添加一个只吃内存的线程:
public class Test {
public static void main(String[] args) {
String dummy = new String("sdfsdfsdf");
WeakReference<String> dummyRef = new WeakReference<>(dummy);
// This thread creates arrays and chucks them.
// Marked as a daemon to ensure it doesn't stop the program
// from quitting.
Thread memEater = new Thread(
() -> {
for( int i=1;;i++) {
int[] arr = new int[6553500];
arr[0] = i;
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
}
}
);
memEater.setDaemon(true);
memEater.start();
Thread test = new Thread(
() -> {
while (true) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
String s = dummyRef.get();
if (s == null) {
System.out.println("String GC'd. Quitting.");
break;
}
System.out.println(s);
s = null;
}
}
);
test.start();
try {
dummy = null;
TimeUnit.SECONDS.sleep(30);
} catch (InterruptedException e) {
}
}
}
我从中得到的输出是:
% java Test
sdfsdfsdf
sdfsdfsdf
sdfsdfsdf
sdfsdfsdf
String GC'd. Quitting.
推荐阅读
- python - 用2个空格Python替换不同数量的空格
- python-3.x - 如何更新熊猫数据框
- python - 通过 API 调用从 Cloud Function 上的实例模板创建 VM
- c - 我需要帮助理解反转字符串的代码
- python - 如何使用 pyTelegramBotAPI 获取相册数据
- r - R 中的微基准测试实际上永远运行
- node.js - 将曲目添加到播放列表 - 使用 fetch 发布请求以发现 API - 不起作用
- git - 如何在本地将活动分支合并到另一个分支?
- javascript - Laravel:我在控制器中编写的 URL 在视图中不起作用
- python - 熊猫:用空白分组替换重复值,例如