在Asynctask中执行一个线程及其复杂性

时间:2014-10-02 07:38:37

标签: android multithreading android-asynctask thread-safety

我想知道在Thread的{​​{1}}方法中执行doInBackground是否可行。我应该避免在我的代码上使用这种结构吗?如果是的话,我为什么要避免呢?这会导致我的应用程序无效吗?

4 个答案:

答案 0 :(得分:4)

原则上,在doInBackground()的{​​{1}}中启动主题没有问题,但有时你看到这不是因为它&#39这是正确的做法,但由于对AsyncTask如何运作的误解。

关键是AsyncTask自动在后台(非GUI)线程上执行,而无需您自己为其创建线程。事实上,这是doInBackground()的重点。因此,如果您想要在后台执行简单的线性任务,则可以使用AsyncTask执行此操作,并且不需要进行任何手动创建线程。

如果您希望后台任务使用多个线程来完成,那么<​​em>可能想要在AsyncTask中启动新线程的位置。假设您正在编写应用程序以检查各种服务器的在线状态,并在屏幕上显示有关其状态的信息。您在后台使用AsyncTask进行网络访问;但是如果你以一种天真的方式做到这一点,你最终会逐一对服务器进行ping操作,这会相当缓慢(特别是如果一个人关闭,你需要等待超时)。更好的选择是确保每个服务器都在自己的后台线程上处理。然后你会有几个选项,每个选项都是可以防御的:

  1. 为每个服务器单独AsyncTask
  2. 为单个AsyncTask的{​​{1}}内的每个服务器创建一个主题,然后确保doInBackground()没有完成,直到所有单个主题都已完成(使用) AsyncTask)。
  3. 在单doInBackground()内使用Thread.join() /某种ThreadPool / fork / join结构,为您管理线程。
  4. 我想说现代图书馆很少需要手动创建线程。库函数将为您管理所有这些,并从中获取一些乏味,并使其不易出错。上面的第三个选项在功能上等同于第二个选项,但只是使用了更多的高级机制,而不是用你的线程创建DIY。

    我并不是说永远不会手动创建线程,但是每当你想要创建一个线程时,值得一问的是,是否有一个高级选项会为您更轻松,更安全地做到这一点。

答案 1 :(得分:3)

  

可以在doInBackground方法中执行一个Thread   的AsyncTask。

是的,但它确实取决于您的应用程序和您的使用情况。例如,在多线程server-client应用中,您必须为每个传入的客户创建一个thread,并且您还必须在另一个thread上进行侦听。所以在另一个内部创建thread是可以的。并且您可以使用asynctask来倾听您的客户。

  

我应该避免在我的代码上使用这种结构吗?如果有,   我为什么要避免它?

如果您仔细设计,则无需避免,例如确保旋转时不会创建另一个asynctask,因为例如,如果您的用户旋转5次,则创建5 asynctasks并且在每个中你创建一个thread,这意味着你将获得10 threads,很快就会出现内存泄漏。

  

这会导致我的应用无效吗?你可以解释吗   请问这些问题。

我在上面做了回答,我认为更好的想法是使用Thread Pool来最小化threads创建asynctask或将UI less fragment包裹在asynctask中的次数,这样你就可以确定了不管发生什么事都会有一个{{1}}。

答案 2 :(得分:2)

在任何更高级的编程语言中,都存在多任务的概念。基本上,用户需要在没有用户交互的情况下运行部分代码。通常为此开发一个线程。但在Android中,可以通过ThreadAsyncTask这三种方法中的任何一种来完成多任务处理。

<强>发

线程是并发执行单元。它有自己的调用堆栈。有两种方法可以在应用程序中实现线程。

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

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

Handler允许您发送和处理与线程的MessageQueue关联的Message和Runnable对象。每个线程都有每个消息队列。 (与待办事项列表一样),线程将接收每条消息并处理它,直到消息队列为空。因此,当Handler进行通信时,它只是向调用者线程发出一条消息,它将等待处理。

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

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

<强>的AsyncTask

AsyncTask可以正确,轻松地使用UI线程。此类允许在UI线程上执行后台操作和发布结果,而无需操纵线程和/或处理程序。异步任务由在后台线程上运行的计算定义,其结果在UI线程上发布。

AsyncTask将经历以下4个阶段:

<强> 1。 onPreExecute()

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

<强> 2。 doInbackground(PARAMS ..)

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

第3。 onProgressUpdate(进步..)

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

<强> 4。 onPostExecute(结果)

在后台计算完成后在UI线程上调用。

互联网上有很多好的资源可以帮助你:

http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html http://www.mergeconflict.net/2012/05/java-threads-vs-android-asynctask-which.html

答案 3 :(得分:0)

如果你需要在AsyncTask旁边同时运行某些东西,我会说没有问题。

一个问题可能是可读性(使用两种不同的并发方式),但我真的看不出其中的危害 - 特别是如果其中一个任务需要在UI中显示它的结果而另一个没有“T