您的位置:首页 > 职场人生

Adnroid 面试题 关于AsyncTask源码解析

2016-03-31 17:11 495 查看

到底AsyncTask线程池的大小是?

总结:

3.0之前的同时运行的线程数、线程池大小是经验值

3.0之后改为了和CPU数目有关系

5.0 版本 ,同一时刻能运行的线程数是CPU的数目+1,线程总池大小是CPU_COUNT * 2 + 1

private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;


4.1.2 版本 规定同一时刻能够运行的线程数为5个,线程池总大小为128

private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;


2.0版本 2.0和4.1.2定义的线程数是一样的,都是5、128

private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;


3.0之后对AsyncTask的改进

区别是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<Runnable>());
new DownloadTask().executeOnExecutor(exec);
//4.1.2中可以使用我们自定义的一个Executor来执行任务,而不是使用SerialExecutor
//上述代码的效果允许在同一时刻有15个任务
//正在执行,并且最多能够存储200个任务。


为什么AsyncTask在UI线程里new实例

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;
}
}
}


解析 SerialExecutor

private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
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

ArrayDeque是Java6新增的一个类,主要是可以实现队列,也可以实现栈。

想比较LinkedList,ArrayDeque底层是用数组实现循环队列的

源码解析 可以看这儿 ArrayDeque源码图析

找出大于某个数的最小2幂次方

这是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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息