AsyncTask

AsyncTask缺陷

1、生命周期

       很多开发者会认为一个在Activity中创建的AsyncTask会随着Activity的销毁而销毁。然而事实并非如此。AsyncTask会一直执行, 直到doInBackground()方法执行完毕。然后,如果 cancel(boolean)被调用, 那么onCancelled(Result result) 方法会被执行;否则,执行onPostExecute(Result result) 方法。如果我们的Activity销毁之前,没有取消 AsyncTask,这有可能让我们的AsyncTask崩溃(crash)。因为它想要处理的view已经不存在了。所以,我们必须确保在销毁活动之前取消任务。总之,我们使用AsyncTask需要确保AsyncTask正确地取消。

       另外,即使我们正确地调用了cancle() 也未必能真正地取消任务。因为如果在doInBackgroud里有一个不可中断的操作,比如BitmapFactory.decodeStream(),那么这个操作会继续下去。

2、内存泄漏

        如果AsyncTask被声明为Activity的非静态的内部类,那么AsyncTask会保留一个对创建了AsyncTask的Activity的引用。如果Activity已经被销毁,AsyncTask的后台线程还在执行,它将继续在内存里保留这个引用,导致Activity无法被回收,引起内存泄露。

3、结果丢失

       屏幕旋转或Activity在后台被系统杀掉等情况会导致Activity的重新创建,之前运行的AsyncTask会持有一个之前Activity的引用,这个引用已经无效,这时调用onPostExecute()再去更新界面将不再生效。

4、并行还是串行

      在Android 1.6之前的版本,AsyncTask是串行的,在1.6至2.3的版本,改成了并行的。

   在2.3之后的版本又做了修改,可以支持并行和串行,当想要串行执行时,直接执行execute()方法,如果需要并行执行,则要执行executeOnExecutor(Executor)。
————————————————

AsyncTask在不同SDK版本中的区别

https://blog.csdn.net/u012236936/article/details/47728691

AsyncTask 是在SDK 1.5 版开始使用,最处运行时是按顺序运行,也就是说在运行多个任务时,AsyncTask 会一个一个的执行这些任务,上一个任务执行完毕才会执行下一个,这样大大的影响了执行效率。

在SDK1.6之后2.3之前AsyncTask的执行顺序修改为并行执行了。如果同时执行多个任务,则这些任务会并行执行,这时的AsyncTask内部的线程池最大数量是5个,也就是说一次最多同时执行5个线程,超出这个范围的只能等待前面的某一个线程执行完再执行。

在SDK3.0开始 google对AsyncTask API进行了又一次调整,调整如下:

     1.又调回了最初了单任务执行,按照先后顺序每次只执行一个,前一个执行完之后才执行第二个。

     2.新增了executeOnExecutor()接口: 这个接口允许开发者提供自定义的线程池来运行,如果需要更多的任务都能同时运行,我们可以创建 一个newCachedThreadPool ()线程池给AsyncTask。这样就改变了AsyncTask的默认状态,使AsyncTask 具有了newCachedThreadPool()的特性。

     3.新增了两个定制线程池SERIAL_EXECUTOR和THREAD_POOL_EXECUTOR:

SERIAL_EXECUTOR : 保证任务执行的顺序,保证提交的任务确实是按照先后顺序执行的。 SERIAL_EXECUTOR 内部有一个队列用来保存所提交的任务,保证当前只运行一个,这样就可以保 证任务是完全按照顺序执行的。

用法:execute() 的默认值就是SERIAL_EXECUTOR 或者executeOnExecutor(AsyncTask.SERIAL_EXECUTOR)。

THREAD_POOL_EXECUTOR:一个corePoolSize为5的线程池,也就是说最多只能有5个线程同时运 行,超过5个的就要等待

用法:executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)

————————————————


AsyncTask两种线程池

 http://bbs.51cto.com/thread-1114378-1.html


1.THREAD_POOL_EXECUTOR, 异步线程池
使用
首先创建一个继承自AsyncTask的MyAsyncTask类,然后调用
MyAsyncTask asynct = new MyAsyncTask(task);
asynct.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 0);
原理
1.corePoolSize=CPU核心数+1;
2.maximumPoolSize=2倍的CPU核心数+1;
3.核心线程无超时机制,非核心线程在闲置时间的超时时间为1s;
4.任务队列的容量为128。
 
  当一个任务通过asynct.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 0)方法欲添加到线程池时:
如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。
当线程池中的线程数量大于 corePoolSize时,如果某线程(非核心线程)空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
也就是:

处理任务的优先级为:
核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务一般为抛出java.util.concurrent.RejectedExecutionException异常)。
 

2.SERIAL_EXECUTOR,同步线程池
使用
它是默认的Executor,所以可以直接调用,所以可以有两种调用方法。
a.    asynct.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, 0);
b.    asynct.execute(0);
原理
SERIAL_EXECUTOR在THREAD_POOL_EXECUTOR的基础上添加了一个mTasks的集合来保证任务顺序执行(异步) 

原文地址:https://www.cnblogs.com/wytiger/p/12221126.html