AsyncTask和Thread/Runnable的区别

61

我有一个让我感到困惑的问题。

假设我想在另一个线程中执行一些操作,比如获取GPS/位置信息,而根据SDK文档的推荐,必须使用后台线程进行。

因此,我的问题是:

  1. 通过AsyncTask在后台创建一个Thread

  2. 创建Thread thread1 = new Thread(new Runnable() ...并实现run()方法

这两者之间的区别是什么?

6个回答

50

AsyncTask 是一个方便的类,用于在新线程上执行某些工作,并在完成时将结果使用调用它的线程(通常是 UI 线程)上使用。它只是一个包装器,使用了一些可运行对象,但处理了创建线程和处理线程间消息传递的所有复杂性。

AsyncTask 可以正确且轻松地使用 UI 线程。这个类允许在后台执行操作并在 UI 线程上发布结果,而无需操作线程和/或处理程序。

AsyncTask 被设计为 Thread 和 Handler 周围的辅助类,并不构成通用线程框架。最好仅将 AsyncTask 用于短时间操作(最多几秒钟)。如果您需要让线程长时间运行,则强烈建议使用 java.util.concurrent 包提供的各种 API,例如 Executor、ThreadPoolExecutor 和 FutureTask。

异步任务由在后台线程上运行的计算和在 UI 线程上发布其结果组成。异步任务由三个泛型类型 Params、Progress 和 Result 定义,以及四个步骤 onPreExecute、doInBackground、onProgressUpdate 和 onPostExecute。

Runnable 接口是 Java 线程的核心。任何想要被线程执行的类的实例都应该实现 Runnable 接口。

此外,如果我引用 这篇博客 中的话:

如果你需要简单编码,请使用 AsyncTask;如果你需要速度,请使用传统的 Java Thread。


1
@AlexGittemeier 即使在这些版本上,你也可以通过使用executeOnExecutor并告诉它使用线程池来运行更多任务,而不仅仅是调用execute。 - Gabe Sechan
1
AsyncTask:处理完成后的响应,Thread:处理完成。 - Tushar Pandey
2
好的。基本上两者是相同的,只是采用了不同的方法? - kevoroid
@GabeSechan executeOnExecutor(...) 是在API 11中添加的。我们是否有选项或能力始终使用它,同时仍支持旧版本? - Alex Gittemeier
1
在11版本之前,默认情况下允许多个异步任务。因此,基本上检查版本,如果低于11,则只需调用execute;如果高于11,则调用executeOnExecutor()。那么唯一无法工作的是2.0之前的版本,在这一点上我不会担心。@AlexGittemeier - Gabe Sechan
显示剩余3条评论

2

请注意,从Android v4.04开始,除非您放弃与较低版本的兼容性,否则一次只能有一个AsyncTasks。请注意!


6
如果您使用executeOnExecutor()(可以有条件地执行,以保持兼容性),则可以实现此功能。 - matiash

2

主要区别:

  1. AsyncTask 是一种异步任务,定义了在后台线程上运行的计算,并将其结果发布到UI线程。除非您在UI线程上使用Handler并发布消息或通过实现适当的同步来直接更改对象的属性,否则无法使用普通线程完成此操作。

  2. 根据开发人员指南有关线程性能的建议,

    需要注意几个重要的性能方面。首先,默认情况下,应用程序将创建的所有AsyncTask对象都推入单个线程中。因此,它们按序列方式执行,并且与主线程一样,特别长的工作包可以阻塞队列。出于这个原因,我们建议只使用AsyncTask处理持续时间短于5毫秒的工作项

    但是正常的Thread可用于长时间运行的任务。

普通Java线程对于Android不太有用,不像Android框架提供的HandlerThread

用于启动具有looper的新线程的便捷类。然后可以使用looper来创建处理程序类。请注意,仍必须调用start()。

请参考下面的帖子以了解更多详细信息:

Handler vs AsyncTask vs Thread


1

AsyncTask已在API级别30中停用。使用线程/Runnable更为方便。


0
最好使用支持库中的新作业调度程序。

1
请详细说明您的答案。如果可能,请添加一些代码。如何回答问题 - Agilanbu

0

AsyncTask类的一个明显缺点是,在Android 3.0之后,异步任务根据启动时间顺序执行。也就是说,除非您通过调用“executeOnExecutor(Executors.newCachedThreadPool())”来执行任务,否则任务将逐个执行。此方法将创建您自己的线程池。


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