Java 从映射中删除对象/实例后,如何将其从内存中删除?

Java 从映射中删除对象/实例后,如何将其从内存中删除?,java,android,object,memory,dictionary,Java,Android,Object,Memory,Dictionary,我在一个公开的地图中保留对本地创建的对象的引用。当我从地图中删除对象时,它也应该从memorynullified中删除 public class X { public boolean infiniteloop = true; public X() { new Thread(new Runnable() { @Override public void run() { while (in

我在一个公开的地图中保留对本地创建的对象的引用。当我从地图中删除对象时,它也应该从memorynullified中删除

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.removeKey之后仍然存在printend。这意味着该对象仍存在于内存中。如何从内存中删除它?

Java会在最适合您的时候从内存中删除对象,所以不用担心。如果你真的想确保线程被终止,你应该保留一个对你的线程和/或Runnable的引用,这样你就可以在必要的时候优雅而突然地关闭线程

如果您想尽快从内存中删除对象,可以尝试尝试尝试System.gc,但这是可以考虑的


使用父实例变量使线程不终止可能有一些技巧,但比我聪明的人肯定可以解释:

Java会在最适合您的时候从内存中删除对象,所以不要担心这一点。如果你真的想确保线程被终止,你应该保留一个对你的线程和/或Runnable的引用,这样你就可以在必要的时候优雅而突然地关闭线程

如果您想尽快从内存中删除对象,可以尝试尝试尝试System.gc,但这是可以考虑的


使用父实例变量使线程不终止可能涉及一些技巧,但比我聪明的人肯定可以解释:

您仅使用remove从映射中删除对象,但对象仍然存在。如果没有对对象的引用,JVM将自动垃圾收集对象。您需要设置x=null以使x对象符合GC的条件。 这将删除对对象的引用

此外,请记住GC过程不是即时的。这是不确定的。它在JVM中的一个单独线程上运行

设置x=null将从原始对象中删除引用。那么该对象符合GC的条件。此外,该对象已从地图中删除,因此地图中对该对象的任何引用也不存在


如果您的对象没有得到GC'ed,请确保在代码的其余部分中没有对该对象的引用。您只提供了伪代码,我认为您应该更广泛地搜索您的问题

您仅使用remove从地图中删除了对象,但对象仍然存在。如果没有对对象的引用,JVM将自动垃圾收集对象。您需要设置x=null以使x对象符合GC的条件。 这将删除对对象的引用

此外,请记住GC过程不是即时的。这是不确定的。它在JVM中的一个单独线程上运行

设置x=null将从原始对象中删除引用。那么该对象符合GC的条件。此外,该对象已从地图中删除,因此地图中对该对象的任何引用也不存在


如果您的对象没有得到GC'ed,请确保在代码的其余部分中没有对该对象的引用。您只提供了伪代码,我认为您应该更广泛地搜索您的问题

正在运行的线程没有看到InfiniteLop变量已更改。 要使此更改可见,您需要添加一些同步。例如,将此变量标记为:

现在应该可以了。不需要做更多的事情,没有x=null之类的东西。
要了解更多信息,请阅读。

正在运行的线程没有看到InfiniteLop变量已更改。 要使此更改可见,您需要添加一些同步。例如,将此变量标记为:

现在应该可以了。不需要做更多的事情,没有x=null之类的东西。
要了解更多信息,请阅读。

可运行不关心它是否在映射中。我认为可运行不是问题所在,因为我在从映射中删除对象之前将inifiniteloop设置为false。不,在线程已经运行后将其设置为false。你可以简单地用调试器检查它。请注意我的答案,你犯了很多错误,比如InfiniteLop应该是布尔InfiniteLop,Runnable应该已经实现了run方法等等。我的简单问题是,你是如何测试上述程序的?@Dev谢谢你改进的代码,我把它添加到了我的问题中。我没有测试我的代码。这是用来澄清我的问题的假代码。它实际上不需要工作。Runnable不关心它是否在映射中。我认为Runnable不是问题所在,因为我在从映射中删除对象之前将InFiniteLoop设置为false。不,在线程已经运行后将其设置为false。你可以简单地用调试器检查它。请注意我的答案,你犯了很多错误,比如InfiniteLop应该是布尔InfiniteLop,Runnable应该实现run方法等等

. 我的简单问题是,您是如何测试上述程序的?@Dev谢谢您改进的代码,我将其添加到我的问题中。我没有测试我的代码。这是用来澄清我的问题的假代码。它确实不需要工作。但是我如何从映射中将x设置为null呢?我不想在映射之外保留对类X的引用,因为一次有多个X实例。当我从映射中删除对象时,我不再需要它了,我想将它从内存中删除。我建议将其降级为遗忘,而且我100%确定,如果其他繁忙线程具有更高的优先级,它将不会被收集和泄漏……从映射中获取值难道不只是复制对象吗?@MeesterPatat Java!=C.如果您想要确定性内存管理,请使用CBut。如何从映射中将x设置为null?我不想在映射之外保留对类X的引用,因为一次有多个X实例。当我从映射中删除对象时,我不再需要它了,我想将它从内存中删除。我建议将其降级为遗忘,而且我100%确定,如果其他繁忙线程具有更高的优先级,它将不会被收集和泄漏……从映射中获取值难道不只是复制对象吗?@MeesterPatat Java!=如果你想要确定性内存管理使用CI,不要认为线程是问题所在,因为当我将inifiniteloop设置为false时,线程会在完成后终止。但是对象x仍然存在于内存中。x类代表蓝牙信标。我的Androidapp为范围内的每个信标创建一个对象,并保留对地图中所有信标对象的引用。当信标不再在范围内时,我想将其完全从地图和内存中删除,以避免在信标对象不在范围内时内存中有很多信标对象。这积累得很快。因此,从内存中删除对象非常重要。gc需要多长时间才能确定不再需要该对象并将其删除?这确实超出了解释gc工作原理的注释范围,我只能参考[Oracle Documentation]www.Oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html。您可能不得不过度思考如何存储对象。不幸的是,我不是Android的专业人士。考虑将Android添加到你的标签中,或者用Android标签和你的用例重新提交你的问题,得到更多有用的答案:“MeestPATAT @ Que0B0LT家伙,我很抱歉,但是这个答案在错误的时候如何被接受?”1作者的问题显然是不正确的同步,即根本没有同步2您不能通过引用Runnable停止线程3您不应该,曾经通过thread.stop 4停止线程你不能通过thread.interrupt停止这个线程,因为代码没有检查中断标志5,你不能通过System.GC保证GC,因为这只是建议JVM运行GC。我不认为线程是问题所在,因为当我将InFiniteLoop设置为false时,线程在停止后被终止完成。但是对象x仍然存在于内存中。x类代表蓝牙信标。我的Androidapp为范围内的每个信标创建一个对象,并保留对地图中所有信标对象的引用。当信标不再在范围内时,我想将其完全从地图和内存中删除,以避免在信标对象不在范围内时内存中有很多信标对象。这积累得很快。因此,从内存中删除对象非常重要。gc需要多长时间才能确定不再需要该对象并将其删除?这确实超出了解释gc工作原理的注释范围,我只能参考[Oracle Documentation]www.Oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html。您可能不得不过度思考如何存储对象。不幸的是,我不是Android的专业人士。考虑将Android添加到你的标签中,或者用Android标签和你的用例重新提交你的问题,得到更多有用的答案:“MeestPATAT @ Que0B0LT家伙,我很抱歉,但是这个答案在错误的时候如何被接受?”1作者的问题显然是不正确的同步,即根本没有同步2您不能通过引用Runnable停止线程3您不应该,曾经通过thread.stop 4停止线程您无法通过thread.interrupt停止此线程,因为代码未检查中断标志5,您无法通过System.GC保证GC,因为这只是建议JVM运行GC。因此,如果我将InFiniteLoop设置为volatile并将其设置为false,线程将被终止,如果我从map,它会立即自动从内存中删除,因为在我的应用程序中没有对它的引用?@meesterpatt这是正确的,除了一件事:没有保证它会立即删除,但它肯定有资格进行进一步的GC。有没有办法立即删除它?Wonderb0lt建议使用System.gc,但这是一个糟糕的做法。@Meesterpatt不,ther
e不是这样。你是对的,System.gc是一种不好的做法,而且,它只是建议JVM运行gc,因此,同样,没有保证它会实际运行。因此,如果我将InFiniteLoop设置为volatile并将其设置为false,线程将终止,如果我从映射中删除对象x,它会立即自动从内存中删除,因为在我的应用程序中没有对它的引用?@meesterpatt这是正确的,除了一件事:没有保证它会立即被删除,但它肯定有资格进行进一步的GC。有没有办法立即删除它?Wonderb0lt建议使用System.gc,但这是一种糟糕的做法。@Meesterpatt不,没有这种方法。您是对的,System.gc是一种不好的做法,而且,它只是建议JVM运行gc,所以同样,没有保证它将实际运行。
public volatile boolean infiniteloop = true;