【问题标题】:Set null to Thread to prevent memory leak in onDestroy Android将 null 设置为 Thread 以防止 onDestroy Android 中的内存泄漏
【发布时间】:2018-08-16 14:57:49
【问题描述】:

我正在使用 Thread 进行一些异步操作。现在我主要有 3 个线程,例如:

private lateinit var horse1Thread: Thread
private lateinit var horse2Thread: Thread
private lateinit var timerThread: Thread

onDestroy() 的活动中调用stop() 会导致UnsupportedOperationException,我想将这些值设置为null 以允许GC 收集并防止内存泄漏。由于我的字段是non-null 类型,我无法将它们设置为null。那么this 是我唯一的选择吗?或者 kotlin 是否提供了一种方法来释放这些字段所持有的内存?我可以将它们的类型设置为可为空,但我觉得它违背了目的?

【问题讨论】:

    标签: android multithreading kotlin garbage-collection non-nullable


    【解决方案1】:

    将它们设置为null 没有任何作用,因为线程仍在运行,虚拟机会在它们运行时跟踪它们。

    您需要做的是引入一种方法来指示线程不应再继续。这通常通过检查循环中的Thread.isInterrupted() 来完成,如果为真则结束循环。然后你只需要在你的onDestroy 方法中调用Thread.interrupt() 来清理线程。

    【讨论】:

    • 嗯..有疑问。当我不保留对它们的任何引用时,GC 不会在内存紧缩的情况下终止我正在运行的线程吗?我知道设置null 不会终止它们,但相当于保留对它们的引用?
    • @ArkaPravaBasu stackoverflow.com/questions/2423284/…。如果 Android 与众不同,我会感到惊讶。
    【解决方案2】:

    我认为您不必关心将这些字段设置为 null。线程应该完成他的工作,之后线程将处于 TERMINATED 状态。稍后垃圾收集器会在没有你的情况下清理它。您应该只关心这些线程的状态,并以这样的方式在这些线程中构建逻辑,使它们在没有任何无限循环的情况下完成工作。

    所以基本上你需要在线程内的长操作中使用一些触发器,通过点击按钮,这个触发器应该跳过(或取消)你在线程内的长操作。之后该线程将自行转到 TERMINATED 线程。

    【讨论】:

      【解决方案3】:

      其实Thread.stop()上甚至有说明为什么不应该使用它:

      https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#stop()

      这种方法本质上是不安全的。使用 Thread.stop 停止线程会导致它解锁所有已锁定的监视器(这是未检查的 ThreadDeath 异常在堆栈上传播的自然结果)。如果以前受这些监视器保护的任何对象处于不一致状态,则损坏的对象将对其他线程可见,从而可能导致任意行为。停止的许多用法应该由简单地修改一些变量以指示目标线程应该停止运行的代码替换。目标线程应该定期检查这个变量,如果变量指示它要停止运行,则有序地从它的run方法返回。

      【讨论】:

        猜你喜欢
        • 2016-07-10
        • 1970-01-01
        • 1970-01-01
        • 2015-04-04
        • 2010-09-21
        • 2011-12-05
        • 2015-02-05
        相关资源
        最近更新 更多