Android并发使用

Geo*_*rge 18 java concurrency multithreading android

Android在同时在不同的线程上执行代码有很多不同的便利.但是我不确定何时应该使用每种方法或者这些不同方式的最佳实践.

  1. 什么时候/为什么要使用处理程序?

  2. 何时/为什么要使用装载机?

  3. 什么时候/为什么要使用AsyncTasks?

  4. 何时/为什么要使用FutureTask?

  5. 什么时候/为什么要使用Executor?

  6. 何时/为什么要使用Threads/Runnables?

  7. 何时/为什么要使用Volley?

我错过了吗?

非常感谢您的帮助!

dco*_*cow 23

你有一个非常大的组件列表,每个组件都解决了稍微不同的问题.我的经验中的两个主要冲突实际上是处理程序执行程序之间,以及任务线程之间的冲突.

概观

主题

线程是用于促进并发的底层系统机制.线程存在于Windows,Unix等中,并且可以以系统认为合适的任何方式实现.创建线程通常非常昂贵(甚至更多 - 以创建全新的流程). 我不知道Dalvik VM是依赖Linux线程还是提供自己的Thread实现. 根据Dalvik虚拟机架构文档,Dalvik VM仅使用Linux线程模型来实现其线程.但是,Dalvik VM不符合Android 4.0之前的Java语言规范的内存模型.

正如你可能知道,因为它是昂贵的创建线程,更好的方法来安排大量的异步计算的是使用线程管理池(大小取决于您的底层硬件的能力),并简单地喂任务管理器,反过来,它会在线程可用时调度任务.

Android处理程序

我理解的历史简短概述是Android开发在Java Executor libraries/api固化之前的几天开始.为了提供比可用的旧线程同步方法更容易混淆的并发接口,并且为了便于在线程之间以良好的方式传递消息,Android引入了Handlers.但是,除非我不正确地理解这一点,否则Handler与Executors基本相同.您将消息(包含Runnables)或简单的Runables传递给Handler,这些消息会在Handler的Thread可以很好地处理它们时排队并执行.

Java执行器

在Android中,线程之间的所有通信都是(或者应该)通过线程的处理程序完成的(根据我的知识,不包括你直接访问另一个线程内存并且可能需要同步的情况).在新的Java中,Executors在功能上等同于Handler,FutureTasks等同于Messages.Runnables仍然是Runnables.只需要执行代码时就使用Runnable.当需要异步执行计算并且需要从计算中检索结果时,使用FutureTask.结果可以是任何类型的对象.因为FutureTask实现了Future接口,所以您也可以轻松地在一个线程中等待Future解析并获得结果.

装载机

加载器只是尝试提供可重用的机制来加载数据(由活动消耗).尽管有文档,但Loader类不是抽象的,也不需要仅用于异步数据采集(尽管我不能想到你将它用于同步加载的情况,我还没有探讨过) .该AsyncTaskLoader只需使用一个的AsyncTask执行负责加载数据的加载的方法.装载机根本没有必要.

例子

主题

线程应该用于支持执行者或处理程序,或者,在其他情况下,您将知道何时需要线程(例如支持服务).对于以自由方式创建,执行和销毁的小任务,通常应该避免使用Threads.

处理程序与执行程序

根据我的经验,在处理UI线程(运行Activity和/或View层次结构)与其他线程之间的消息传递时,最好坚持使用Handler.但是,在实现自己的异步功能时,使用Executors或Handler似乎是完全安全的.例如,我可能有一个类来管理要从服务器获取的图像队列.我可以简单地创建自己的执行程序,并在我认为合适的情况下向该执行程序提供任务.但是,当将消息消息传递回Activity时,其中一个图像已加载并且应该使用结果数据设置视图,我使用Activity的Handler获得了最佳结果(通过runOnUiThread()方法)而不是创建一个在Activity的线程上运行并向其发布Runnables的执行程序.目前还不清楚为什么后者不能一直工作(从文档来看),但我怀疑这样做会导致行为类似于Handler的runWithScissors()方法. (编辑,我现在意识到在一个线程上运行多个并发"loopers"是非常糟糕的做法 - 所以这解释了.)

我想一个好的经验法则可能是:

  • 在Android组件之间传递消息时使用处理程序.
  • 实现自己的库或实用程序功能时,请使用Executor或Handler.

Runnables vs FutureTasks vs AsyncTasks

如前所述,Runnables是一个简单的接口,用于在对象之间传递计算.只有在涉及线程/执行器/处理程序时才需要使用Runnables - 它们可用于捕获状态和重用代码.

  • Runnables和FutureTasks与Executors一起使用.
  • AsyncTasks(隐式)与Handler一起使用.构造AsyncTask时,您提供对活动的引用,AsyncTask类便于在工作线程池中的一个线程上执行doInBackground方法(这由Executor内部管理).为此,使用Handler在活动线程和任务的线程之间传递消息.但是,任务本身由Executor管理,并在可用时传递给工作线程.

装载机

我不使用装载机.但是,当您拥有需要加载的数据以便Activity使用它时,可以使用它们.如果您在处理数据方面遵循ContentProvider惯用法,则可以将CursorLoader与ContentProvider一起使用.

齐射

我从未使用过截击,所以我怀疑我对该频道有任何有用的见解.


免责声明:我不是Android历史的权威.无论如何,我希望概述有助于增加清晰度.

  • @dcow~"装载机根本没必要".你为什么这么说?它们消除了为保留对数据库连接的单例引用而必须编写的大量样板代码,以及在配置更改时保留游标状态. (2认同)