我在公开的地图中保留对本地创建的对象的引用。当我从地图中删除对象时,它也应该从内存中删除(无效)。
public class X {
public boolean infiniteloop = true;
public X() {
new Thread(new Runnable() {
@Override
public void run() {
while (infiniteloop) {
System.out.println("Still exists");
}
}
}).start();
}
public class Y{
Map myMap = new HashMap();
public Y() throws InterruptedException{
X x = new X();
myMap.put("Key", x);
Thread.sleep(10000);
((X)myMap.get("Key")).infiniteloop= false;
myMap.remove("Key");
}
}
在上面的代码中,"仍然存在"在myMap.remove之后打印(" Key")。这意味着该对象仍然存在于内存中。如何从内存中删除它?
答案 0 :(得分:2)
Java负责在最佳时刻从内存中删除对象,所以不用担心。如果你真的想确保线程被终止,你应该保留对Thread
和/ Runnable
的引用,这样你就可以尝试优雅地关闭线程(如果需要,可以突然关闭)。
如果您想尝试尽快从内存中删除对象,可以尝试System.gc()您可以尝试使用System.gc(),但这被视为bad practice
使用所涉及的父实例变量可能会涉及到使得线程不能终止的一些技巧,但是比我聪明的人可以肯定地解释:)
答案 1 :(得分:2)
您只使用remove
从地图中删除对象,但该对象仍然存在。 JVM将Garbage如果没有对象的引用,则自动收集对象。您需要设置x=null
以使X对象符合GC条件。
这将删除对象的引用。
另外,请记住GC流程不是即时的。这不是确定性的。它在JVM中的一个单独的线程上运行。
设置x = null将从原始对象中删除引用。然后该对象符合GC的条件。此外,该对象已从地图中删除,因此对地图内对象的任何引用也不存在。
如果您的对象没有获得GC,请确保在其余代码中没有对该对象的引用。您只提供了伪代码,我认为您应该更广泛地搜索您的问题
答案 2 :(得分:1)
正在运行的线程未看到infiniteloop
变量已更改。
要使此更改可见,您需要添加一些同步。例如,将此变量标记为volatile:
public volatile boolean infiniteloop = true;
现在它应该工作了。无需再做任何事情,不需要x=null
和其他东西。
要了解更多信息,请参阅Java Memory Model。