工作线程WorkThread和异步任务AsyncTask取舍

来源:互联网 发布:matlab智能算法工具箱 编辑:程序博客网 时间:2024/05/01 15:43

在应用开发过程中多线程技术是必不可少的手段,而如何对多线程并发和线程调度进行优化往往是其中最为核心的部分。出于对包括用户体验在内的多种因素的考虑,Android不允许主线程阻塞,当主线程阻塞5秒以上,应用程序即失去响应,由此也衍生出Android编程的一些原则,譬如主线程不得进行耗时操作,工作线程不能更新用户界面等等。源于这些原则,我们所有的耗时操作都要放在工作线程中进行,而且当需要在工作线程完成某项操作之后更新界面,则可使用一个发消息的工具向主线程发消息,主线程接受到消息之后在适当的时候更新界面,达成良好的线程交互。

实际上,几乎所有的应用都必然包含耗时操作,某些方面是局限于硬件性能,有些时候则是由于网络,使用习惯等各种不确定因素,因而我们不可能在主线程中完成所有的工作,或多或少都会启动一些工作线程,让这些工作线程帮我们完成各种消耗大量时间的操作。

在使用工作线程时,我们常常在开始创建一个工作线程,在线程里面写好它需要执行的任务,然后在合适的时机启动它,这样工作线程就开始为我们工作了,与主线程不同,Android的特性决定了工作线程只能在用户不能触及的地方默默工作。工作线程的工作必然也是为了达成某项结果,那么当它完成这项工作之后,如何让用户知道知道呢?前面说过了,可以使用一个发消息的工具,这个工具名叫Handler,每个线程都有一个Handler,由这个线程的任务队列决定,取得某个线程的Handler之后即可向此线程发送消息。当工作线程完成任务之后取得主线程的Handler,向主线程发送消息,用户通过接收消息就能知道。不仅工作线程能向主线程发消息,主线程也能向工作线程发消息,而且任何线程之间都能互相发消息,只要他们处于同一个进程下,这就是线程交互的原理。

在Android系统框架中有一个AsyncTask对象,我们常称为“异步任务对象”,使用的时候把耗时或者一些不需要用户关心的操作交给它,然后等待结果即可,在它的doInBackground()方法中执行耗时操作,在onPostExecute()方法中取得结果,而且不用考虑繁杂的线程问题。

从使用的便利性来看,异步任务对象无疑是耗时操作的最佳选择,我们根本不用考虑线程之间的交互,似乎异步任务对象根本就没有工作线程这玩意。后来,经过研究源码了解到异步任务对象的原理,它的底层其实也是由线程池ExecutorService加Handler实现的,Google将它们封装起来,使开发者能轻易地完成一些耗时和线程交互工作。

虽然Google的技术员很强,但AsyncTask对象也不是万能的。在AsyncTask中,由线程池完成线程的调度(有关池的概念会在其他篇章中讲述),在doInBackground()方法中启动工作线程并执行耗时操作,完成进度和结果由Handler发送给主线程,在onProgressUpdate()方法 和onPostExecute()方法中处理结果。有时候不能满足需求的地方在于:AsyncTask中的任务队列是阻塞式的,并没有多少的并发量,因而在我们有意大量并发的时候达不到要求。

在面向对象程序开发时,我常常陷于很多选择的矛盾中,到底是优先选择别人写好的框架还是自己从基础部分逐渐实现所需功能。由于经验短浅,在自己实现功能的过程中往往挫折丛丛,效率不高;而使用强大的三方框架能简单快速地实现功能,效率非常高。而另一方面,在遇到问题或者别人写好的框架不能满足自己的需求时,使用三方框架的人可能觉得非常棘手,三方框架虽然强大,但在自己能力不足的时候,理解起来也很困难,出了问题只能寄希望于别人的指导,在需要基于框架扩展功能的时候,由于源码不开放或者即便开放但自己并不理解,所以无能为力,如果是自己从基础部分实现的功能,虽然很蹩脚,但非常了解,可能随时扩展和维护。毕竟,这个社会是一个讲究效率的社会,完全由自己蹒跚独步并不明智,很多时候善于利用工具能发挥更大的功效,究竟如何选择,需要我们根据实际的工作需要,结合自己的目标,在这数者之间寻找一个平衡。

0 0