?
1.问题由来:
? ? 1.在SDK2.3环境下,开发下载模块时,核心下载线程通过ansyncTask,当下载任务为>=5个时,应用中的其他用ansyncTask实现的操作都被阻塞而没有被执行,下载也最多只有五个;
? ? 2.在SDK4.0环境下,下载模块中,只能有一个下载任务下载。当有一个下载任务,再添加一个下载任务时,不能添加,不能同能下载;
? ?
2.问题原因分析:
? ? ? ?1.针对问题一:
?
? ? ? ? 1)原因:
? ? 因为下载中的后台非主线程实现类是android 的AsyncTask。查看其源代码,发现其实质是用到了java的线程池:
? ? privatestaticfinalintCORE_POOL_SIZE = 5; //表明线程池大小为5,意思是同时最多只允许5个线程调度和执行。
? ? 这样,当其他的操作用到AsyncTask时,这些操作将被阻塞,因此才出现了上面的问题
?
? ? 2)解决方案:
? ? 1)不使用android的ansyncTask,直接使用java的线程调度API
? ? 2)修改最大同时下载任务由5个改成3个。这也是为什么现在的android的相关app应用最大下载任务数基本都是2或者3个。因为现在app下载基本都是用的AnsyncTask实现,最大下载任务数基本都是2或者3个。
?
? ? 2.对与问题二 :
? ?1)原因:
? ? 1. Android2.3以前的版本,也即SDK/API 10和以前的版本
? ? 内部的线程池限制是5个,也就是说同时只能有5个线程运行,超过的线程只能等待,等待前面的线程某个执行完了才被调度和运行。换句话说,如果一个进程中的AsyncTask实例个数超过5个,那么假如前5个都运行很长时间的话,那么第6个只能等待机会了。这是AsyncTask的一个限制,而且对于2.3以前的版本无法解决。如果你的应用需要大量的后台线程去执行任务,那么你只能放弃使用AsyncTask,自己创建线程池来管理Thread,或者干脆不用线程池直接使用Thread也无妨。不得不说,虽然AsyncTask较Thread使用起来比较方便,但是它最多只能同时运行5个线程,这也大大局限了它的实力,你必须要小心的设计你的应用,错开使用AsyncTask的时间,尽力做到分时,或者保证数量不会大于5个
? ??从Android 3.0开始对AsyncTask的API做出了一些调整:
? ? #execute()提交的任务,按先后顺序每次只运行一个也就是说它是按提交的次序,每次只启动一个线程执行一个任务,完成之后再执行第二个任务,也就是相当于只有一个后台线程在执行所提交的任务(Executors.newSingleThreadPool())。
? ? 2)解决方案
? ? 1.新增了接口#executeOnExecutor()
? ? 这个接口允许开发者提供自定义的线程池来运行和调度Thread,如果你想让所有的任务都能并发同时运行,那就创建一个没有限制的线程池(Executors.newCachedThreadPool()),并提供给AsyncTask。这样这个AsyncTask实例就有了自己的线程池而不必使用AsyncTask默认的。
2.新增了二个预定义的线程池SERIAL_EXECUTOR和THREAD_POOL_EXECUTOR
?
其实THREAD_POOL_EXECUTOR并不是新增的,之前的就有,只不过之前(Android 2.3)它是AsyncTask私有的,未公开而已。THREAD_POOL_EXECUTOR是一个corePoolSize为5的线程池,也就是说最多只有5个线程同时运行,超过5个的就要等待。所以如果使用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)就跟2.3版本的AsyncTask.execute()效果是一样的