【问题标题】:Thread keeping a reference forever线程永远保持引用
【发布时间】:2012-07-20 23:38:29
【问题描述】:

我有一堂课:

class RenderView implements Runnable {
   Thread renderThread;
   public void  run() {
        while(!Thread.currentThread().isInterrupted()) {
            //does some work
        }
} 

//At some point in executed code, inside RenderView class (i'm sure it's executed)
renderThread = new Thread (this);

//When activity is closed (also, i'm sure this part is executed)
renderThread.interrupt();

renderThread 真的停止了(至少,run() 方法退出了)。

但由于某种原因,在我退出活动后,我的代码中仍然有一些对 renderView 的引用。这导致我出现巨大的内存泄漏。

hprof 转储告诉我: java.lang.Thread(这个在 GC Root 中) 有参考 目标(mypackage.RenderView)

我不知道为什么这个 Thread 类会保留对我的 Thread 的引用,即使我已经完成了 Thread!有什么想法吗?

编辑:在 Activity B 中引用了 renderView。因此,当我退出 Activity 时,应该仍然无法访问对 renderThread 的引用。但我仍然尝试设置 renderThread = null :不起作用。正如我通过 MAT Analyzer 发现的那样,让 renderView 不被垃圾收集的唯一原因是 java.lang.Thread 的这个奇怪的引用。

【问题讨论】:

  • Android 中的解决方案是不管理线程。在 runOnUIThread 上使用 AsyncTask 应该适用于大多数情况。
  • 但是如果您发现了这些不起作用的特殊情况,请详细说明。

标签: java android memory-management


【解决方案1】:

为什么不直接使用 AsyncTask 或 runOnUIThread()?

我从来没有看到需要你做什么。也许有一个,否则只使用 AsyncTask 或 runOnUIThread。不要重新发明轮子。

【讨论】:

  • 我不知道我在重新发明轮子……我来看看这个函数。谢谢。
  • runOnUIThread 并不为人所知。如果此或 AsyncTask 对您有用,请将问题标记为已回答。谢谢
  • 只是题主有点分歧。在与 SDK 2.3 一起提供的示例中,我已经在 Lunar Lander 等示例中看到了线程的使用。使用您的建议重新实现代码也需要我一段时间。我暂时只是试图降低我的内存泄漏。我非常感谢你的帮助。当我使用您的建议重新实现我的代码时,如果它解决了内存泄漏,我会将您的答案标记为正确。我只是不知道现在标记它是否正确。不过谢谢你的回答。
  • 这是着陆器的月球部分。
【解决方案2】:

释放你的线程实例

renderThread = null;

线程实例与任何其他实例一样,是一个对象。即使它完成运行,您仍会保留对它的引用,直到您释放它。

【讨论】:

  • 问题是,我丢失了对包含 renderThread 的 renderView 的活动的引用,但仍然保留了一些奇怪的引用。请参阅编辑。无论如何我都尝试过无效(你永远不知道),但没有奏效。
【解决方案3】:

您是否尝试取消 renderThread

【讨论】:

    【解决方案4】:

    实际上,renderThread.interrupt 可能不会停止线程,它只是设置一个标志和信号 JVM,它可以被中断。这就是为什么你的线程仍然在运行。最好的做法是优雅地退出 run 方法只是在 while 循环中设置一个标志。

        while(isRunning){
    
        }
    
    // at some point, say 
    
        isRunning = false;
    

    可以从以下链接获得有关 Android UI 设计的最佳实践。

    Android UI design pattern:

    【讨论】:

    • 哦,我只是像这个标志一样使用中断,你可以在我的代码中看到。我做了一会儿(!Thread.currentThread().isInterrupted())。当你调用 renderThread.interrupt() 时,线程确实退出了(我已经测试过了;实际上到达了 while 之后的代码)。
    • @userEng15,可能是这样做退出了循环,但线程没有停止。这就是为什么在你的分析器中,它仍然可见。
    • renderThread.getState() 显示“已终止”。如果它的 run() 已经逃脱,它怎么能不被阻止呢?我有这个作为它被停止的定义。
    • 实际上,android UI 在单线程上运行。所以如果你有任何其他功能,那么你可以使用 spawn 一个子线程。但是使用@Code Droid 建议的最佳实践来实现它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    • 2010-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-12
    • 2022-06-16
    相关资源
    最近更新 更多