AsyncTask的一些小细节

来源:互联网 发布:讨鬼传2捏脸数据女 编辑:程序博客网 时间:2024/06/05 08:03

学习Android的人对AsyncTask应该都不陌生,这个类是基于消息机制封装的一个类,目的是方便开发者使用。对AsyncTask的基本使用方法就不赘述了,郭霖和鸿洋的博客中都写得很清楚了,感谢二位大神。这里记录一些使用AsyncTask时的小细节。

关于AsyncTask只能被执行一次

准确来讲,是一个AsyncTask对象只能被执行一次,即同一个AsyncTask对象,不能多次调用其execute()方法。
为什么呢?原因大概是同一个任务,执行的肯定是相同的逻辑,可能涉及到对同一块内存区域的读写,如果开启一个以上的线程进行相同的任务,由于线程执行时间的不确定性,无法保证数据的原始性,会造成混乱(可能内部没有锁吧)。
那如何防止开发者多次调用execute()方法呢?也很简单,在AsyncTask对象初始化的时候在其中设置一个final变量的引用,执行execute()之前先检查该变量,并且在开始执行后对该变量进行赋值。这样第二次执行execute()方法的时候会检测到不同的该变量,那么这时候直接报错就好了。

参考文献:http://blog.csdn.net/lintcgirl/article/details/48440543

关于AsyncTask内部线程的调度

在API10以前,AsyncTask同时能运行5个线程,其余线程必须等待。
在API10之后,使用execute()方法开启的AsyncTask,使用同一个线程池,且所有的任务串行执行,也就是说同时只有一个任务在执行,当该任务执行完毕后,后面的任务才能执行。这不是开倒车吗?之前还能同时执行5个,现在只能同时执行一个?其实并不是,Google同时提供了executeOnExecutor()方法供开发者使用非默认的线程池。顾名思义,要在该方法中传入一个Executor对象才行。

关于Executor的说明请看这篇文章:
Java并发编程

同时Google还提供了两个预定义的线程池(还有比这更贴心的吗?):
1. executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) —和API10之前一样,可以同时执行5个任务。
2. executeOnExecutor(AsyncTask.SERIAL_EXECUTOR) —和execute()一样,只能同时执行一个。

如果想自定义线程池,可以这样写:

Executor exec = new ThreadPoolExecutor(15, 200, 10,      TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());  

关于线程池的初始化可以参考上面的文章或下面的参考文章:
参考文献:
http://blog.csdn.net/hitlion2008/article/details/7983449

PS:我一直在思考“封装”这个概念,对于老手来说,封装确实方便了使用,但是对于新手来说,封装也隐藏了内部的实现细节,使得新手只知其然而不知其所以然,不出问题还好,一出问题就束手无策了。所以我觉得,如果时间和精力允许的话,对于封装过的模块还是尽量了解下其内部基本实现会比较好。

原创粉丝点击