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)
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试