AsyncTask基本使用懂android的都会,但还是有必要整理一下AsyncTask的实现原理,一方面是巩固学习到的知识,另一方面也是为了更深层次的理解AsyncTask的实现。因为我在以前使用AsyncTask 过程的时候一知半解,造成一些代码的问
题。
http://blog.csdn.net/lmj623565791/article/details/38614699
看过hongyang的分析AsyncTask的实现原理的这篇博客,我明白了3.0以前AsyncTask是支持多个线程同步执行任务的,但是3.0及3.0以后AsyncTask实际上是单线程执行的。 也就是说3.0以后我们使用不同的AsyncTask实例去执行任务,还是需要等待之前的任务执行结束,后续任务才能执行。
但是还是有个疑惑,为什么之前AsyncTask使用配置的线程池执行任务,最多同时执行128个任务,并等待10个, 并且超过限制会报异常呢?
来看看AsyncTask内部的线程池的配置。
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(10);
public static final Executor THREAD_POOL_EXECUTOR
=new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
http://zhangfengzhe.blog.51cto.com/8855103/1881644
这部分其实是线程配置方面的知识,我们在java中构建自定义线程池时,需要用到ThreadPoolExecutor的构造方法。如下所示:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
}
参数说明如下:
corePoolSize:核心线程数
maximumPoolSize:最大线程数
keepAliveTime + unit:线程回收时间
workQueue:任务较多时暂存到队列
threadFactory:执行程序创建新线程时使用的工厂
handler:超出线程池容量以及队列长度后拒绝任务的策略
从AsyncTask的构建线程池的代码中可以看出,其中构建的是一个corePoolSize为5,maximumPoolSize为128,任务队列为无界队列LinkedBlockingQueue,队列容纳个数为10. 根据线程池处理流程图:
我们可以知道,开始可以并行执行5个任务,当任务个数超过corePoolSize核心数时,就会添加到任务队列中,当超过10个的时候就会一直构建新线程去执行任务,一直到线程数量达到128个(线程池的最大数量)。 所以在3.0以前, AsyncTask最多可以同时执行128个任务,同时队列中可以有10个在等待。 如果超过这个数字,就会报RejectedExcpction的异常(超出线程池容量以及队列长度后拒绝任务的策略)。
另1:构建线程池的时候可以使用队列,其中无界队列LinkedBlockingQueue,可以在构建时指定队列容量。
另2:我在使用ScheduledThreadPoolExecutor线程池的时候遇到了 RejectedExcpction异常,我想ScheduledThreadPoolExecutor使用的线程池的队列是无界的,怎么会导致出现这个问题。 后来看到文档说明,如果在执行任务的时候线程池已经“shutdown" 就会拒绝执行。 所以使用线程池执行任务的时候,需要先判断线程池是否已经shutdown();