总结:
3.0之前的同时运行的线程数、线程池大小是经验值
3.0之后改为了和CPU数目有关系
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
区别是4.1.2是串行执行多个AsyncTask,而2.0版本是并行执行
注意4.1.2提供了executeOnExecutor方法,可以指定AsyncTask的Executor
public final AsyncTask<Params, Progress, Result> executeOnExecutor (Executor exec, Params... params)
可以利用自定义的Executor把串行改为并行
下面部分内容摘自郭霖的博客 Android AsyncTask完全解析,带你从源码的角度彻底理解
3.0之前是使用Java自带的ThreadPoolExecutor
在3.0版本中AsyncTask的改动还是挺大的,在3.0之前的AsyncTask可以同时有5个任务在执行,而3.0之后的AsyncTask同时只能有1个任务在执行。为什么升级之后可以同时执行的任务数反而变少了呢?这是因为更新后的AsyncTask已变得更加灵活,如果不想使用默认的线程池,还可以自由地进行配置。比如使用如下的代码来启动任务:
Executor exec = new ThreadPoolExecutor(15, 200, 10,
TimeUnit.SECONDS, new LinkedBlockingQueue());
new DownloadTask().executeOnExecutor(exec);
//4.1.2中可以使用我们自定义的一个Executor来执行任务,而不是使用SerialExecutor
//上述代码的效果允许在同一时刻有15个任务
//正在执行,并且最多能够存储200个任务。
InternalHandler 是为了在UI线程中执行更新控件等操作
OnPreExecute、onProgressUpdate、onPostExecute都是在UI线程中执行,内部也都调用了InternalHandler的handleMessage方法
由于静态成员在加载类的时候进行初始化,这就要求AsyncTask的类必须在主线程中加载。
private static final InternalHandler sHandler = new InternalHandler();
private static class InternalHandler extends Handler{
public void handleMessage(Message msg){
AsyncTaskResult result = (AsyncTaskResult)msg.obj;
switch(msg.what){
case MESSAGE_POST_RESULT:
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
private static class SerialExecutor implements Executor {
final ArrayDeque mTasks = new ArrayDeque();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
ArrayDeque是Java6新增的一个类,主要是可以实现队列,也可以实现栈。
想比较LinkedList,ArrayDeque底层是用数组实现循环队列的
源码解析 可以看这儿 ArrayDeque源码图析
这是ArrayDeque里面的一个方法,ArrayDeque保证长度要是2的幂次方,方便一些按位与、掩码等运算。
private void allocateElements(int numElements) {
int initialCapacity = MIN_INITIAL_CAPACITY;
// 找到numElements的最小的2的幂整数。
// Tests "<=" because arrays aren't kept full.
if (numElements >= initialCapacity) {
initialCapacity = numElements;
initialCapacity |= (initialCapacity >>> 1);
initialCapacity |= (initialCapacity >>> 2);
initialCapacity |= (initialCapacity >>> 4);
initialCapacity |= (initialCapacity >>> 8);
initialCapacity |= (initialCapacity >>> 16);
initialCapacity++; //上面得到2的幂次方-1
if (initialCapacity < 0) // Too many elements, must back off
initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
}
elements = (E[]) new Object[initialCapacity];
}
stackoverflow的回答解释了为什么按位或就能得到2的幂次方-1
Implementation of ArrayDeque.allocateElements (bitwise operations)
initialCapacity |= (initialCapacity >>> 1);
initialCapacity |= (initialCapacity >>> 2);
initialCapacity |= (initialCapacity >>> 4);
initialCapacity |= (initialCapacity >>> 8);
initialCapacity |= (initialCapacity >>> 16);
//equals to:
initialCapacity |= (initialCapacity >>> 1) | (initialCapacity >>> 2) |
(initialCapacity >>> 3) | (initialCapacity >>> 4) |
(initialCapacity >>> 5) | (initialCapacity >>> 6) |
(initialCapacity >>> 7) | (initialCapacity >>> 8) |
(initialCapacity >>> 9) | (initialCapacity >>> 10) |
(initialCapacity >>> 11) | (initialCapacity >>> 12) |
(initialCapacity >>> 13) | (initialCapacity >>> 14) |
(initialCapacity >>> 15) | (initialCapacity >>> 16) |
(initialCapacity >>> 17) | (initialCapacity >>> 18) |
(initialCapacity >>> 19) | (initialCapacity >>> 20) |
(initialCapacity >>> 21) | (initialCapacity >>> 22) |
(initialCapacity >>> 23) | (initialCapacity >>> 24) |
(initialCapacity >>> 25) | (initialCapacity >>> 26) |
(initialCapacity >>> 27) | (initialCapacity >>> 28) |
(initialCapacity >>> 29) | (initialCapacity >>> 30) |
(initialCapacity >>> 31)