我一直在阅读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)
}
}
}
为什么会选择使用一组执行者?你用它做了什么,只有一个执行者你不能做到这一点?
这只是为他们可能执行的正确工作构建和分配正确的执行者:
Runnable
s的线程,执行程序创建的每个线程可以一次运行一个作业:
diskIO
(来自constrcutor
)是一个Executors.newSingleThreadExecutor()
,因为任务最好排队并一次执行一个以减少写入和读取锁定或竞争条件,例如。因此,无论有多少人排队确保设计,SingleThreadExecutor
一次只能运行一项任务。作为单个线程也可能意味着它被用于将应用程序日志写入文件,例如,这允许以提交给执行者的正确顺序写入日志。因此,单个线程最好按照排队的作业顺序维护输出。
networkIO
是一个Executors.newFixedThreadPool(3)
,因为任务通常与网络相关,如连接到互联网上的服务器以及执行请求或获取数据。这些任务通常使用户等待(可能在几秒到几分钟之间)并且需要并行执行并快速执行,以便在需要同时执行许多请求的情况下缩短等待时间。因此,这个执行器使用3个线程的原因是在它们之间分配任务并一起执行。这里的工作顺序不是问题,因为工作需要花费不同的时间来执行,但最重要的是它们并行运行。
mainThread
是一个MainThreadExecutor()
,它在Android应用程序中处理UI并绘制它。 UI应该能够顺利运行而不是滞后,因此使用上述两个执行程序的原因是让任何繁重的任务(如编写文件或执行请求)在后台运行或与应用程序的mainThread
分开运行。即使应用程序未向其提交任何内容,此执行程序仍会执行任务。它一直在执行的任务是在屏幕上不断重复绘制UI。 mainThread
执行的任务需要轻量级和快速(他们花费的时间大约是几毫秒),因此任何减慢它的任务都会被注意到,因为mainThread
正在忙着完成任务,因此UI将会滞后或出现故障而不是绘制和更新UI。这里的mainThread
只使用了Handler
,它是Android SDK /架构的一部分,具有单线程类型,其行为类似于执行器(有一些差异),它们将任务排队以创建/更新UI。只有Handler
才能执行UI任务,其他任何执行者都无法执行。