服务、线程和进程
Posted
技术标签:
【中文标题】服务、线程和进程【英文标题】:Services, threads, and process 【发布时间】:2017-02-02 00:32:20 【问题描述】:在recent answer,我读到
服务不在自己的线程上运行,它在 UI 线程上运行
我在许多其他与服务相关的问题中阅读过类似的陈述。
如果我从Activity
调用startService()
,Service
会在Activity
的 UI Thread
上运行,还是会使用自己的 UI Thread
生成一个新进程?
如果它在Activity
的用户界面Thread
上运行,这不会导致Activity
无响应吗?
【问题讨论】:
【参考方案1】:是的,服务确实在主线程上运行,关于 ANR(应用程序未响应)问题,如果您的服务使用 CPU 进行长时间处理工作,则 ANR 的可能性会更高,因此官方文档还建议使用 Worker Threads
以提高效率. docs
您必须阅读文档中的警告段落以确认
如果您的任务是一次性完成的,则使用 IntentService
隐式使用线程机制进行处理,但 IntentService
会在任务完成时自动销毁,因此您下次必须重新启动它等等。
android:process :使用它在另一个进程中启动服务会导致使用更多内存。这将导致在单独的堆内存空间中为您的应用创建两个进程,这也需要其他维护。所以这很少使用,我不建议将其用于常规服务任务。
【讨论】:
谁投反对票,请发表评论并说明理由【参考方案2】:如果我从
Activity
调用startService()
,Service
会继续运行吗Activity
的 UIThread
或者它是否产生了一个新进程 自己的 UIThread
?
如果它是Service
(不是IntentService
),它将在您的应用程序进程的主Thread
上运行,只要您没有明确将其定义为单独的进程(通过添加@987654330清单中的@标签)。
如果它在
Activity
的用户界面Thread
上运行,那不会冒着使Activity
没有反应?
是的,如果您执行 CPU 密集型/阻塞操作。
为防止这种情况发生,您可以从您的 Service
开始新的 Thread
(s),或使用 IntentService
,这将自动生成一个新的工作人员 Thread
用于其工作。
【讨论】:
【参考方案3】:来自Services Docs,它清楚地解释了您的答案。
注意:服务在其托管进程的主线程中运行—— 服务不创建自己的线程,也不在单独的线程中运行 过程(除非您另有说明)。这意味着,如果您的 服务将执行任何 CPU 密集型工作或阻塞操作 (如 MP3 播放或联网),你应该创建一个新线程 在服务内完成这项工作。通过使用单独的线程,您 将降低应用程序无响应 (ANR) 错误的风险,并且 应用程序的主线程可以保持专用于用户交互 与您的活动。
【讨论】:
【参考方案4】:在最近的回答中,我读到
A service does not run on its own thread, it runs on the UI thread
这完全是错误的。 Service
是一个对象(一个类的实例)。它不在任何线程上运行,它根本不运行。它只是“是”。 Service
的方法可以在任何线程上运行,具体取决于...
具体来说,直接从 android 框架调用的Service
(onCreate()
、onStartCommand()
等)的生命周期方法在主 (UI) 线程上运行,它们可能相同也可能不同调用startService()
的线程。但是,Service
可以(并且通常会)启动其他后台线程,只要它需要,就可以执行必要的工作。
如果我从 Activity 调用 startService(),Service 会在 Activity 的 UI 线程或者它是否使用自己的 UI 生成一个新进程 线程?
见上文。如果您希望 Service
在单独的进程中运行,可以通过在清单中的 <service>
声明中指定 android:process=":service"
来实现。默认情况下,服务与应用程序的其他组件(Activity
、BroadcastReceiver
等)在同一进程中运行。
如果它在 Activity 的 UI 线程上运行,那不会冒着使 活动无响应?
这取决于您的Service
在做什么!显然,如果您的 Service
在 UI 线程上进行大量计算密集型处理,它会使您的应用程序无响应。如果您的 Service
在 UI 线程上执行 I/O,Android 通常会抛出异常(在更新的 Android 版本中)。这就是服务通常启动后台线程来工作的原因。但是,如果您的 Service
是轻量级的,那么您的 Service
的方法没有理由不能在 UI 线程上运行。正如我所说,这取决于...
【讨论】:
“这完全是错误的......”我认为你在这里有点迂腐。根据上下文和大小写,“服务”一词可以具有多种含义。Service
是一个类,当然,我们可以创建这个类的实例。但是,我认为“服务”可以有效地引用内存中的可执行代码,它本质上是生命周期方法和它们调用的方法。
@Code-Apprentice 对不起,我不同意。在 Android 中,Service
是一个非常具体且重要的概念/组件。我的 cmets 对您来说可能听起来很迂腐,但实际上有成千上万的 Android 开发人员甚至对这些组件是什么以及它们的实际工作方式都没有基本的了解。 “清除空气”并让 Android 开发恢复理智的唯一方法是抓住一切机会与这种错误信息作斗争。
另外,如果您查看链接到的问题/答案,很明显该人指的是 Android Service
(组件),而不是一般的计算概念。
【参考方案5】:
IntentService 在后台线程上运行,因此,如果您想执行一次性任务,请使用它。
【讨论】:
IntentService
不在后台线程上运行。 IntentService
的生命周期方法在主(UI)线程上运行,与所有服务的生命周期方法相同。 IntentService
创建一个(或多个)工作线程,用于通过调用onHandleIntent()
(在工作线程上调用,而不是在主(UI)上调用)来“完成工作”IntentService
线)。但是,IntentService
并不总是解决问题的最佳方法,因此建议 OP 在不了解他的应用程序的情况下使用 IntentService
是没有帮助的。以上是关于服务、线程和进程的主要内容,如果未能解决你的问题,请参考以下文章