在Android中,Asynctask与Thread的区别

155

在UI中,为了执行一些后台工作,我使用了一个独立的Thread。但是根据其他人的建议,现在我正在使用AsyncTask

ThreadAsyncTask之间的主要区别是什么?

在哪种情况下,应该使用ThreadAsyncTask


5
请访问 https://dev59.com/wmw05IYBdhLWcg3w41wp#9800870 进行查看。 - JavaDM
@Webaldo.at 我参考了这个网站,他们在这里给出了Asynctask和Thread之间的描述和区别。我想知道在哪些情况下例如网络连接、文件读取等我应该使用哪一个? - Ram
线程 -> 无法访问UI线程|| 异步任务 -> 对UI线程的有条件访问 - JavaDM
对于后台任务,IntentService是另一个不错的选择。 - Chen
1
可能是Handler vs AsyncTask vs Thread的重复问题。 - Ciro Santilli OurBigBook.com
6个回答

166

对于长时间运行或 CPU 密集型任务,基本上有两种方法可以实现:Java 线程和 Android 的本地 AsyncTask。

没有哪种方法比另一种更好,但知道何时使用每种调用是利用系统性能为您带来好处的关键。

使用 AsyncTask 来:

  1. 简单的网络操作,不需要下载大量数据
  2. 可能需要超过几毫秒的磁盘绑定任务

使用 Java 线程来:

  1. 涉及中等到大量数据的网络操作(上传或下载)
  2. 需要在后台运行的高 CPU 任务
  3. 任何您想相对于 GUI 线程控制 CPU 使用率的任务

还有许多互联网上的良好资源可供使用:

http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html


我可以问一下为什么下载数据量是个问题吗? - Yeung
2
@Yeung 看起来你需要了解关于异步任务的知识!看,数据量越大,完成相同操作所需的时间就越长。因此,使用异步任务进行长时间运行的过程并不是一个好的实践,原因如下:1. 异步任务与 Activity 生命周期绑定不佳。2. 它们会导致内存泄漏。 - Mohit
3
请看这个链接:https://dev59.com/0Wcs5IYBdhLWcg3wgkIQ?rq=1该链接讨论了在Android中使用AsyncTask处理需要长时间运行的操作的方法。请仔细阅读并按照指示进行操作。 - Mohit
谢谢。我现在明白风险了。 - Yeung
1
@Impasse @Yeung 在我看来,数据量并不是问题,网络操作的关键问题在于操作所需的时间。即使只下载几个字节,在服务器繁忙、无法访问(超时)等情况下,也可能需要很长时间。解决方法可以是使用具有自己调度程序的“AsyncTask”。 - xmedeko
显示剩余2条评论

48
如果您使用Java线程,那么您需要在自己的代码中处理以下要求:

如果您将结果返回到用户界面,则需要与主线程同步

没有默认选项用于取消线程

没有默认线程池

Android中没有默认选项用于处理配置更改


4
这段话更能说明为什么不应该使用简单的线程,因为它解决了这个问题的原因。从我的记忆中,任何需要与Activity/Service生命周期相关联的内容都应该使用AsyncTask,即使您需要手动在任务内“优雅地降级”资源,但至少当Activity被销毁时,您不会让任务挂起。 - leRobot

34

线程

  • 一般指长时间的任务
  • 通过thread.start()方法启动
  • 可以从任何线程触发
  • 自己的线程上运行
  • 手动管理线程可能使代码难以阅读

异步任务

  • 一般指需要与主线程通信的小任务
  • 通过execute()方法启动
  • 必须从主线程创建和执行
  • 工作线程上运行

我不理解“Runs on its own thread”和“Runs on worker thread”的区别是什么? 自己的线程和工作线程之间有什么区别? - imany apk

14

线程

线程是并发执行的基本单位,它有自己的调用栈。 在应用程序中实现线程有两种方法。

一种是提供一个扩展Thread类并覆盖其run()方法的新类。另一种是在创建时提供一个带有Runnable对象的新Thread实例。可以通过调用线程的“start”方法来执行线程。您可以通过调用线程的“setPriority(int)”方法来设置线程的“优先级”。

如果您对UI部分没有影响,则可以使用线程。例如,您正在调用某些Web服务或下载某些数据,并且下载后正在将其显示到屏幕上。然后,您需要使用Handler和Thread,这将使您的应用程序处理来自线程的所有响应变得复杂。

Handler允许您发送和处理与线程的MessageQueue相关联的消息和Runnable对象。每个线程都有自己的消息队列。 (就像待办事项列表),线程将获取每个消息并处理它,直到消息队列为空。因此,当处理程序进行通信时,它只会将消息传递给调用线程,并等待处理。

如果使用Java线程,则需要在自己的代码中处理以下要求:

如果要将结果发布回用户界面,则需要与主线程同步没有默认的取消线程没有默认的线程池没有Android处理配置更改的默认值

异步任务

AsyncTask使UI线程的使用正确而容易。此类允许在不必操作线程和/或处理程序的情况下执行后台操作并在UI线程上发布结果。异步任务由在后台线程上运行且其结果在UI线程上发布的计算定义。

AsyncTask将经历以下4个阶段:

onPreExecute()

在任务执行之前在UI线程上调用

doInBackground(Params..)

在onPreExecute()执行完成后立即在后台线程上调用。

onProgressUpdate(Progress..)

在调用publishProgress(Progress...)之后在UI线程上调用。

onPostExecute(Result)

在后台计算结束后在UI线程上调用。

为什么应该使用AsyncTask?

易于在UI线程中使用。(因此,在调用线程是UI线程时,请使用它。)

无需操作处理程序。

有关更多信息,请访问这里


6

线程:

Thread 应该被用于将长时间运行的操作与主线程分离,以提高性能。但是它不能优雅地取消操作,并且不能处理 Android 的配置更改。你不能从 Thread 更新 UI。

AsyncTask 可以用于处理执行时间小于 5ms 的工作项。使用 AsyncTask,你可以更新 UI,不像Java中的Thread。但是许多长时间运行的任务会影响性能。

你还有其他几个选择。

HandlerThread/HandlerThreadPoolExecutor

查看下面的帖子以了解更多详细信息:

Handler vs AsyncTask vs Thread


0

如果您有需要同时运行以利用CPU核心并缩短时间延迟的长任务,您应该绝对使用多线程线程

  • 您可以从后台线程初始化线程或(初始化可以作为内部线程),不像AsyncTask
  • 您不需要继承父类和覆盖方法(更清洁和精确)。
  • 您可以使用多线程自己管理并发性,只需阅读有关VolatileAtomicity的内容。
  • 要在UI上发布,请使用同步线程并使用UIhandler通知UiThread

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接