如果我无限期在后台运行Android线程会发生什么

时间:2018-07-12 03:39:39

标签: android multithreading android-8.0-oreo background-thread

Android文档指示Oreo对后台执行有新的限制:https://developer.android.com/about/versions/oreo/background。这似乎是合理的,并且他们明确地希望使平台更像iOS,并防止应用在后台猖ramp运行。

我不清楚的一件事(实际上根本没有记录)是当UI进入后台时您可以在线程上执行的操作。具体来说,

  

鉴于我使用

创建了一个线程
new Thread(() -> { 
     // Naughty thread doing something forever
}).start();
  

然后我将应用发送到后台

     

那时...该线程发生什么了?

我已经创建了非常简单的代码来执行此操作,并且我的线程已经愉快地将logcat切换了10分钟以上而没有任何问题。

有人对此线程有什么限制有任何清楚的信息吗?我本以为,由于Android限制了后台服务可以执行的操作,因此它也将限制此类线程可以执行的操作。

请注意,我们没有计划编写一款可以执行此类操作的应用程序。我们只希望能够编写安全的代码,而不会在较新版本的android上引起问题。在iOS上,如果您进入后台,那么您将有一段宽限期来结束您所做的任何事情(并且您可以要求更多的时间),但最终您的线程将被暂停。

4 个答案:

答案 0 :(得分:1)

  

任何人都没有关于存在哪些限制的任何明确信息   在这样的线程上?我本以为既然Android限制了   后台服务可以做什么,这也将限制   线程可以做到。

此类线程可以运行多长时间没有任何限制。只要您的应用程序在后台运行,您就可以继续在后台执行Thread

但是,由于线程不会无限运行,因此您需要考虑如何正常终止/释放线程。如果操作系统在内存不足时需要放弃内存,则托管此后台活动的应用程序进程将终止,最终破坏线程。如果处理不当,将导致线程/内存泄漏。

答案 1 :(得分:0)

如@Sagar的回答所述,尽管系统可以有选择地终止“后台服务”,但它没有有选择地终止单个“后台线程”。

但是您的问题不仅仅是避免终止,还有更多的问题。您希望线程连续执行 。本页上的其他答案没有提到WakeLocks,并且在这方面有一些误导性的评论,因此我将在这里解决。

我们正在处理两个独立的问题:应用终止和设备睡眠。

应用终止:Android终止应用以释放资源-优先使用后台中的应用(例如,不在屏幕上且不包含{{3} }。当您的应用终止时,其所有线程也会终止。

设备睡眠:当设备进入睡眠状态时,Android 会暂停您的线程,因为它会暂停所有线程。这就是在移动设备上实现的大量电池节省:CPU进入低功耗“待机”模式,并停止执行指令。即使设备可能正在休眠,您的应用程序(及其线程)仍然存在。

  • 使用前台服务阻止您的应用离开屏幕后被终止。
  • 使用WakeLock(PARTIAL_WAKE_LOCK)将CPU保持在可以执行的状态,即使屏幕可能关闭。

拥有前台服务不会不会阻止设备进入睡眠状态。同样,持有WakeLock并不会阻止您的应用终止。请注意,foreground service。有关处理此问题的一种方法,请参见newer versions of Android can ignore WakeLocks in doze

拥有Foreground服务并不能保证您的代码将比后台服务执行得更快。前景服务不会“终止”打ze睡。

如果您的日志继续打印10分钟,我建议这可能是因为您的设备已插入电源。在大多数Android设备上,插入电源后CPU仍处于唤醒状态(即使屏幕可能关闭了)。

答案 2 :(得分:0)

根据我对仿真器API 26和27的测试,只要应用程序仍在后台且未终止,并且已启动的线程将继续工作,并且系统不会决定终止该线程或终止该应用程序

我甚至使用以下命令强制模拟器进行深度打do:

$ adb shell dumpsys deviceidle force-idle

但是,线程仍然在运行。 但是,这在实际的物理设备上不会发生。进入休眠状态时线程会暂停。因此,根据经验,不要完全信任模拟器。

因此,正如您在问题中提到的,您的观察是正常的。

对此:

  

任何人都没有关于存在哪些限制的任何明确信息   在这样的线程上?我本以为既然Android限制了   后台服务可以做什么,这也将限制   线程可以做到。

在消耗内存和电池方面,线程本身一直比服务本身少关注的问题。在棉花糖之前,即使您关闭了应用程序,服务也可能永远保持运转,并且如果系统杀死了该应用程序以回收内存,它们会在(START_STICKY)之后重新启动。因此,这种行为在电池消耗和资源消耗方面很危险。

另一方面,线程在应用程序终止后立即终止,并且不会再次自动启动。另外,系统宁愿终止一个后台应用程序,即使有很多正在运行的线程,也不会运行任何服务,而不是运行有服务的后台应用程序。

从开始棉花糖开始,他们引入了打ze模式,仅在手机进入睡眠状态时才暂停几乎所有内容,以节省电池电量。但是,这仍然不能解决用户当前不使用的应用程序的问题,因为该问题在设备退出休眠状态后立即在后台进行大量工作(服务),并使用户正在运行的应用程序的性能下降。

因此,从Oreo开始,他们对不处于前台的应用程序服务施加了限制,因为它们是造成性能危害的主要原因。 因此,也许将来它们也会在后台时对应用程序的线程施加限制,以进一步改善资源消耗。

答案 3 :(得分:-1)

只要您在App处于前台时启动线程,该线程就可能(我的意思是)在App进入后台时继续运行。

但是,如果电话的内存不足,并且系统决定回收内存,该线程将被杀死。在低端设备上经常会发生这种情况。您需要看一下Android GO。

替代: 无论如何,您可以利用 JobScheduler 或经过改进的新的 WorkManager 来实现与运行线程可能想要实现的功能相同的功能。由于JobScheduler和WorkManager是由Android系统管理的,因此可以确保无论系统上的约束如何,功能都可以正常工作。此外,在使用JobScheduler / WorkManager时,您可以指定包含诸如网络/电池之类的内容。这是使用线程时不会得到的。