Android工作线程持续多长时间?

Posted

技术标签:

【中文标题】Android工作线程持续多长时间?【英文标题】:How long do Android worker threads last? 【发布时间】:2017-05-15 06:44:23 【问题描述】:

我看过一些关于这个主题的帖子,但没有一个给出令人满意的答案。

假设我在其onCreate() 方法中从我的主(唯一)Activity 启动一个工作线程。然后我调用finish() 导致Activity 终止。

此时,它所属的任务被销毁(因为其中不再有任何Activity)。然而,应用程序(以及运行它的进程)可能会继续以空的“骨架”形式存在,以便在需要时可以快速重新启动它(尽管它很容易被系统杀死)。

假设以上是正确的——工作线程什么时候被杀死?是不是只有系统主动销毁进程才被杀死?

就我而言,我的工作线程作为蓝牙连接的侦听器存在;收到后,它将再次启动所需的Activity。在这种情况下,没有正在运行的组件(ActivityServiceContentProviderBroadcastReceiver)。在我看来,这应该可行,只是有些东西正在杀死我的工作线程。

我知道我可以通过使用背景Service 来做到这一点(并且痛苦更少)。但是,我很好奇为什么这不起作用。

谢谢, 巴里

【问题讨论】:

相信只有在Linux进程被销毁的时候,Thread才会被自动杀死。 “在我看来,这应该可行,只是有些东西正在杀死我的工作线程” 这只能表示system terminated the app process。 “是否只有在系统主动销毁进程时才被杀死?”正确(或者如果run()方法返回)。 同意。那么问题就变成了,该进程何时被终止?我的猜测是,当没有更多正在运行的组件时它会被杀死,但我还没有在任何地方看到明确记录。下面是我对 Oleg 的 BroadcastReceiver 响应的更多信息。 【参考方案1】:

工作线程什么时候被杀死?是不是只有系统主动销毁进程才被杀死?

-> 工作线程在其run 函数中的所有代码执行完毕后才算熟练。即使您的activity 被销毁,它仍然可以运行。

就我而言,我的工作线程作为蓝牙连接的侦听器存在;收到后,它将再次启动所需的活动。在这种情况下,没有主动运行的组件(Activity、Service、ContentProvider 或 BroadcastReceiver)。在我看来,这应该可行,只是有些东西正在杀死我的工作线程。

要使其正常工作,在这种情况下,您需要有一个背景 service,并从您的工作线程或更简单地使用 EventBus 启动 soft/weak 引用您的 service Service 中的任何组件为:

 EventBus.getDefault().post(new BlueToothEvent()); // call in your worker thread
// do something in your service
onBlueToothEventFired(BlueToothEvent  e);

【讨论】:

【参考方案2】:

android App lifecycle 有一个很好的例子,非常热门:

流程生命周期错误的一个常见示例是 BroadcastReceiver 当它收到一个 Intent 时启动一个线程 BroadcastReceiver.onReceive() 方法,然后从 功能。一旦它返回,系统就会认为 BroadcastReceiver 不再处于活动状态,因此不再需要其托管过程 (除非其他应用程序组件在其中处于活动状态)。所以,系统 可以随时终止进程以回收内存,并且这样做, 它终止进程中运行的衍生线程。

简而言之,如果您的线程有机会运行直到终止或进程将被提前终止,这真的不是很可预测,您绝对不应该依赖任何顺序/行为。

值得一提的是,即使您完成()它,leak 您的活动也很容易与线程一起使用,但如果它是您的最后/唯一活动,它不会改变图片

【讨论】:

只有在 Activity 有引用的情况下才会泄露 Activity。如果他的 Thread 不以任何方式引用 Activity 并且是静态内部类或非内部类,则 Activity 没有泄漏,而只有 Thread 类持有的引用。 他不需要显式引用,在 onCreate 中说 new Thread() ... 就可以得到隐式引用和繁荣 不,不是。仅当 Thread 是非静态内部类时才如此。您的示例是哪个(它是一个非静态匿名内部类),但不一定是这种情况。静态内部类没有对父类的引用。 鉴于作者没有显示任何关于线程的代码,我显然在谈论我的示例,所以我无法理解哪个部分是“不,它不是”,抱歉 我已将此答案标记为“正确”。总结:Android系统不会终止工作线程。它们将一直存在到:1) run() 完成或 2) 应用程序进程被终止。当没有更多组件在其中运行时,应用程序进程很容易被杀死,因此一个工作线程运行会使其(以及整个进程)很快被杀死。进程何时被杀死是一个比这里讨论的更广泛的话题。【参考方案3】:

当您启动一个线程时,它独立于启动它的父级。在您的情况下,这是您的应用程序活动。这意味着在 Run 方法完全执行之前,您的线程将继续存在。

如果您退出应用程序(并因此调用 Activity 的 onStop 方法),线程仍将存在,您将导致内存泄漏。如果内存不足,它最终会被系统杀死。

由于您提到您创建了一个侦听器来侦听蓝牙连接,因此您的线程可能在收到任何事件之前就死了(如果没有任何代码 sn-p,我不可能知道)。它也可能会崩溃,这将结束线程。

【讨论】:

只有当 Thread 持有 Activity 引用时才会发生内存泄漏。 线程可以持有对活动以外的事物的引用,这会导致所述引用的泄漏 澄清:我希望工作线程继续存在,并且我小心不要在它之后生成任何新线程。至少从概念上讲,这将允许它接受传入的蓝牙请求并在发生这种情况时启动相关的活动。所以不会有内存泄漏(只要我仔细编码工作线程)——只是我打算为工作线程保留的内存。 我没有,事实证明(根据我的原始帖子)。当我从我的唯一 Activity 调用 onCreate() 中的 finish() (并从 onCreate() 返回)时,进程中没有更多组件在运行,并且需要清理系统;在此后不久的某个时刻,该进程被终止,并且工作线程以及其他所有内容都消失了。相比之下,如果我要创建一个 Service 并使用它来创建一个工作线程,则该 Service 将继续作为进程中的一个组件,并且该进程被杀死的可能性要小得多(我想你已经知道了 :-) )。 你能把你线程的run方法的代码贴出来吗?我缺少一些东西。服务也可能无法达到您的预期【参考方案4】:

Android 中有一个主(也称为 UI)线程。这是您的应用程序使用的唯一线程,除非它通过Thread.start()AsyncTask.execute() 等显式启动一个线程。所有活动、服务、广播接收器等都在该主线程上运行它们的所有生命周期方法。请注意,我包含了服务——服务在主线程上运行,除非它启动自己的线程(IntentService 是个例外,它确实在自己的线程上运行)。

您创建的Thread 一直持续到Runnable 从其运行函数返回(或者当然进程终止)。这可以超过创建它的Activity/Service 的末尾。然而,这样的线程仍然存在于组件的原始实例中,并且如果在没有大量特殊工作的情况下重新启动一个新实例,则无法访问新实例的变量(请参阅加载器模式)。

【讨论】:

作者在哪里提到了与您的陈述相矛盾的内容?他刚刚从 onCreate 产生了一个线程 @OlegBogdanov 我最初误解了他的问题,认为 onCreate 启动了一个线程。我删除了你错了部分。

以上是关于Android工作线程持续多长时间?的主要内容,如果未能解决你的问题,请参考以下文章

当用户离线时,Firebase 身份验证会话会持续多长时间?

Android中的onLongPress事件多长时间?

Android中的onLongPress事件多长时间?

Android中的onLongPress事件多长时间?

Android Service演义

我如何计时在android中需要多长时间