【发布时间】:2014-10-02 07:38:37
【问题描述】:
我想知道在Asynctask 的doInBackground 方法中执行Thread 是否可以。我应该避免在我的代码中使用这种结构吗?如果是,我为什么要避免它?这会导致我的应用程序无效吗?
【问题讨论】:
标签: android multithreading android-asynctask thread-safety
我想知道在Asynctask 的doInBackground 方法中执行Thread 是否可以。我应该避免在我的代码中使用这种结构吗?如果是,我为什么要避免它?这会导致我的应用程序无效吗?
【问题讨论】:
标签: android multithreading android-asynctask thread-safety
原则上,在AsyncTask 的doInBackground() 中启动线程是没有问题的,但有时您会看到这样做不是因为这样做是正确的,而是因为对 AsyncTask 工作原理的误解。
重点是doInBackground() 将自动在后台(非 GUI)线程上执行,而无需您自己为其创建线程。事实上,这就是AsyncTask 的全部意义所在。因此,如果您想要在后台执行一个简单的线性任务,您可以使用 AsyncTask 来完成它,并且您不需要进行任何手动线程创建。
您可能想要在AsyncTask 中启动一个新线程的地方是,如果您希望您的后台任务使用多个线程来完成。假设您正在编写一个应用程序来检查各种服务器的在线状态,并在屏幕上显示它们的状态。您可以使用AsyncTask 在后台进行网络访问;但是,如果您以天真的方式进行操作,最终会导致服务器被一个一个地 ping 通,这会相当慢(特别是如果一个服务器宕机,并且您需要等待超时)。更好的选择是确保每个服务器都在其自己的后台线程上处理。然后,您将有几个选项,每个选项都是可辩护的:
AsyncTask。AsyncTask 的doInBackground() 内为每个服务器创建一个线程,然后确保在所有单独的线程都完成之前doInBackground() 不会完成(使用Thread.join())。AsyncTask 中使用 ThreadPool / 某种 ExecutorService / fork/join 结构来管理线程。我想说,现代库很少需要手动创建线程。库函数将为您管理所有这些,并从中消除一些乏味,并使其不易出错。上面的第三个选项在功能上与第二个相同,但只是使用了更多的高级机制,而不是自己创建线程。
我并不是说永远不应该手动创建线程,但是当您想创建一个线程时,值得询问是否有一个高级选项可以更轻松、更安全地为您创建线程。
【讨论】:
可以在doInBackground方法里面执行一个Thread吗 异步任务。
是的,但它确实取决于您的应用程序和您的使用情况。例如,在多线程server-client 应用程序中,您必须为每个传入客户端创建一个thread,并且您还必须监听另一个thread。所以在另一个内部创建thread 是可以的。您可以使用asynctask 倾听您的客户。
我应该避免在我的代码中使用这种结构吗?如果是的话, 我为什么要避免它?
如果您仔细设计它,则无需避免,例如,确保在旋转时您不会创建另一个 asynctask,因为例如,如果您的用户旋转 5 次,您会创建 5 个 asynctasks 并且在每个你创建了一个thread,这意味着你会得到10个threads,很快你就会得到内存泄漏。
这会导致我的应用程序无效吗?你可以解释吗 请问这些问题。
我在上面回答过,我认为更好的办法是使用Thread Pool 来尽量减少创建threads 或将asynctask 包装在UI less fragment 中的次数,这样你就可以确定你有一个asynctask,不管是什么会发生的。
【讨论】:
在任何高级编程语言中,都有多任务的概念。基本上,用户需要在没有用户交互的情况下运行部分代码。通常为此开发一个线程。但是在Android中,多任务可以通过Thread和AsyncTask这三种方法中的任何一种来完成。
线程
线程是一个并发的执行单元。它有自己的调用堆栈。在应用程序中实现线程有两种方法。
其中一个提供了一个新类,它扩展了 Thread 并覆盖了它的 run() 方法。 另一种是在创建过程中提供一个带有 Runnable 对象的新 Thread 实例。 一个线程可以通过调用它的“start”方法来执行。您可以通过调用其“setPriority(int)”方法来设置线程的“优先级”。
如果您对 UI 部分没有影响,则可以使用线程。例如,您正在调用一些网络服务或下载一些数据,下载后,您将其显示到屏幕上。然后你需要使用一个带有线程的处理程序,这将使你的应用程序处理来自线程的所有响应变得复杂。
处理程序允许您发送和处理与线程的 MessageQueue 关联的 Message 和 Runnable 对象。每个线程都有每个消息队列。 (就像一个待办事项列表),线程将获取每条消息并处理它,直到消息队列为空。所以,Handler在通信的时候,只是给调用者线程一个消息,等待处理。
如果您使用 Java 线程,那么您需要在自己的代码中处理以下要求:
异步任务
AsyncTask 允许正确且轻松地使用 UI 线程。此类允许在 UI 线程上执行后台操作和发布结果,而无需操作线程和/或处理程序。异步任务由在后台线程上运行的计算定义,其结果在 UI 线程上发布。
AsyncTask 会经历以下 4 个阶段:
1. onPreExecute()
在任务执行之前在 UI 线程上调用
2。 doInbackground(Params..)
onPreExecute() 执行完成后立即在后台线程上调用。
3。 onProgressUpdate(Progress..)
在调用 publishProgress(Progress...) 后在 UI 线程上调用。
4. onPostExecute(结果)
在后台计算完成后在 UI 线程上调用。
互联网上有很多很好的资源可以帮助你:
http://www.vogella.com/articles/AndroidBackgroundProcessing/article.htmlhttp://www.mergeconflict.net/2012/05/java-threads-vs-android-asynctask-which.html
【讨论】:
如果您需要在AsyncTask 旁边同时运行某些东西,我会说这样做没有问题。
一个问题可能是可读性问题(使用 2 种不同的并发方式),但我真的看不出其中的危害 - 特别是如果其中一项任务需要在 UI 中显示其结果,而另一项则不需要不。
【讨论】: