我一直在Android文档中阅读有关Executor的信息。如果我理解正确,它将用于多线程管理,并且可以为您完成一些工作,例如在需要时生成新线程。或者,您可以选择自己管理东西。
在下面的示例中,使用了一组执行器而不是一个。因此,它就像一个线程池(?)。
/**
* Global executor pools for the whole application.
*
* Grouping tasks like this avoids the effects of task starvation (e.g. disk
reads don't wait behind
* webservice requests).
*/
@Singleton
open class AppExecutors(
private val diskIO: Executor,
private val networkIO: Executor,
private val mainThread: Executor
) {
@Inject
constructor() : this(
Executors.newSingleThreadExecutor(),
Executors.newFixedThreadPool(3),
MainThreadExecutor()
)
fun diskIO(): Executor {
return diskIO
}
fun networkIO(): Executor {
return networkIO
}
fun mainThread(): Executor {
return mainThread
}
private class MainThreadExecutor : Executor {
private val mainThreadHandler = Handler(Looper.getMainLooper())
override fun execute(command: Runnable) {
mainThreadHandler.post(command)
}
}
}
为什么要选择使用一组执行者?您仅凭一个执行者就无法实现这一目标?
答案 0 :(得分:2)
这只是为可能执行的正确工作构造并分配正确的执行者:
Runnable
的线程,并且执行者创建的每个线程可以一次运行一个作业:
diskIO
是{来自constrcutor
的{{1}},因为最好将任务一次排队并一次执行,以减少例如写入和读取锁定或竞争条件。因此,Executors.newSingleThreadExecutor()
一次只能运行一项任务,无论有多少队列确保该设计。成为单个线程还可能意味着它例如用于将应用程序日志写入文件中,从而允许将日志以提交给执行者的正确顺序进行写入。因此,单线程最适合按作业排队的顺序维护输出。SingleThreadExecutor
是networkIO
,因为任务通常与网络有关,例如连接到Internet上的服务器并执行请求或获取数据。这些任务通常会使用户等待(可能在几秒钟到几分钟之间),并且需要并行且快速地执行以缩短等待时间,以防万一需要同时执行许多请求。因此,此执行程序使用3个线程的原因是在其中分配任务并一起执行。这里的作业顺序不是问题,因为作业需要花费不同的时间来执行,但最重要的是它们并行运行。Executors.newFixedThreadPool(3)
是mainThread
,它在Android应用中用于处理UI并进行绘制。用户界面应运行平稳且不会滞后,因此,使用上述两个执行程序的原因是让任何繁重的任务(如编写文件或执行请求)在后台运行,或与应用程序的MainThreadExecutor()
分开运行。即使应用程序未向其提交,该执行程序也会继续执行任务。它一直执行的任务是在不断重复的屏幕上连续绘制UI。 mainThread
执行的任务需要轻巧,快速(花费的时间以毫秒为单位),因此会降低速度的任何任务都会被注意到,因为UI会滞后或出现故障,因为{{ 1}}忙于完成该任务,而不是绘制和更新UI。 mainThread
在这里仅使用mainThread
,它是Android SDK /体系结构的一部分,是单线程类型,其行为类似于执行程序(有一些区别),该执行程序将创建/更新UI的任务排队。只有mainThread
可以执行UI任务,其他执行程序则不能。