大约Android 3.0后AsyncTask默认的单线程分析
在Android下了很大的后台操作在需要的情况下。通常用于AsyncTask这个类。比方说,网络负载形象。访问server接口。一般的情况是使用一个的一例AsyncTask对象mTask,复制AsyncTask抽象方法doinBackgroud等等,最后运行task.execute(params),然后就能够在UI线程上方便的取得后台线程的运行结果;
AsyncTask运行中终于触发的是把任务交给线池THREAD_POOL_EXECUTOR来运行,提交的任务并行的在线程池中运行。但这些规则在3.0之后发生了变化,3.0之后提交的任务是串行运行的。运行完一个任务才运行下一个!
先看看3.0曾经的代码;
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 10;
</pre><p></p><pre>
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
3.0曾经线程池里核心线程有5个,同一时候存在的线程数最大不能超过128个。线程池里的线程都是并行执行的。
可是在3.0之后,直接调用execute(params)触发的是sDefaultExecutor的execute(runnable)方法。而不是原来的THREAD_POOL_EXECUTOR
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 KEEP_ALIVE = 1;
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
看看这个sDefaultExecutor与原来的THREAD_POOL_EXECUTOR线程池有什么 区别,sDefaultExecutor实际上是指向SerialExecutor的一个实例,从名字上看是一个顺序运行的executor;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; 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);
}
}
}
分析SerialExecutor,当提交一个任务。运行一次execute(),向mTasks加入一个runnable。此时mActive为null。接着会运行scheduleNext(),将mActive指向刚刚加入的runbale,并提交到THREAD_POOL_EXECUTOR中运行,接着就线程池中就会运行以下这段代码。
try {
r.run();
} finally {
scheduleNext();
}
当asyncTask提交大量的任务时。会反复之前的流程。任务都加入至mTasks中了,提交第一个任务之后,mActive便不再为Null了,之后的任务假设要被运行就必需等到前一个任务run方法跑完,也就是try{ }语句块中的run(),前一个任务运行完后,才会调用finally
后面的scheduleNext()从mTasks中取出下一个任务来运行。
分析完上面的代码后,如今对于3.0以后AsyncTask默认情况下同一时候仅仅存在一个线程顺序运行的原理就了解清楚了;
假设想要提交的任务在能并行运行呢?这在网络图片显示中还是比較实用的;
AsyncTask也为我们提供了第二种启动方法
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params)
这里能够指定自己定义的executor,而不再用SerialExecutor,假设乐意的话当然也能够直接使用用原本的THREAD_POOL_EXECUTOR,这样就能够保证多个任务并行运行了。
版权声明:本文博客原创文章,博客,未经同意,不得转载。
大约Android 3.0后AsyncTask默认的单线程分析的更多相关文章
- IIS6(Win2003) 使用.net 4.0 后,默认文档失效解决方案。
IIS6(Win2003) 使用.net framework 4.0 后,默认文档失效解决方案. 用.net framework 4.0 开发的WEB项目,但放到iis6 中无法使用默认文档,状况如下 ...
- android 4.0后不允许屏蔽掉home键
屏蔽home键的方法 // 屏蔽掉Home键 public void onAttachedToWindow() { this.getWindow().setType(WindowManager.Lay ...
- Android Studio安装后配置默认新工程目录以及.gradle,.android,.m2和system,config目录
关于在哪里设置:以下所有设置都是在没有打开工程的前提下设置的, Configure > Settings 如图: 不要使用 Configure > Project Defaults> ...
- 转 Android 4.0后,自定义Title报错 You cannot combine custom titles with other title feature
自定义Titlebar时为了避免冲突 需要修改:AndroidManifest.xml android:theme="@style/mystyle" styles.xml文件中 ...
- Android 6.0 M userdebug版本执行adb remount失败
[FAQ18076]Android 6.0 M版本默认会打开system verified boot,即在userdebug和user版本会把system映射到dm-0设备,然后再挂载.挂载前会检查s ...
- Android 5.0之后屏幕截图的方法
截图的几种方法 Android获取屏幕截图主要有以下三种方法 1.通过view.getDrawingCache()获取指定View的绘制缓存来实现截屏. 这种方式Android 5.0之前也可以,且不 ...
- Android权限管理之RxPermission解决Android 6.0 适配问题
前言: 上篇重点学习了Android 6.0的运行时权限,今天还是围绕着Android 6.0权限适配来总结学习,这里主要介绍一下我们公司解决Android 6.0权限适配的方案:RxJava+RxP ...
- Android 5.0之前屏幕截图的方法
截图的几种方法 Android获取屏幕截图主要有以下三种方法 1.通过view.getDrawingCache()获取指定View的绘制缓存来实现截屏. 这种方式Android 5.0之前也可以,且不 ...
- Android 9.0适配遇到的问题1
文章同步自javaexception 本周在适配Android 9.0,过程中碰到了小问题 问题1: SSL handshake timed out 解决办法: Android 9.0 开始,默认不允 ...
随机推荐
- 如何有效抓取SQL Server的BLOCKING信息
原文:如何有效抓取SQL Server的BLOCKING信息 转自:微软亚太区数据库技术支持组 官方博客 http://blogs.msdn.com/b/apgcdsd/archive/2011/12 ...
- DOM笔记2
<!-- 节点类型检查 if(someNode.nodeType==ElementNode){ alert("Node is an element"); } 或者 if(so ...
- C++ 静态static 变量在 cocos2d-x 里面使用误区
void Cms::showMonster(CCArray* monsterArray,int type) { <span style="color:#ff0000;"> ...
- Javascript继承之最佳实践
尊重原创,转载请注明出处:http://blog.csdn.net/zoutongyuan 什么是继承? 继承是面向对象最显著的一个特性.继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和 ...
- 通过java.util.concurrent写多线程程序
在JDK 1.5之前,要实现多线程的功能,得用到Thread这个类,通过这个类设计多线程程序,需要考虑性能,死锁,资源等很多因素,一句话,就是相当麻烦,而且很容易出问题.所幸的是,在JDK1.5之后, ...
- 体验安装金蝶K/3 Wise 13.0(图像)
金蝶13.0它提供windows7支持,而数据库也升级到SQL server 2008,有许多功能上的改善和增强.原本在位置低版本号需要时间来管理此功能,因为有这个模块没有原因一直没能起来,现在,新版 ...
- JavaEE(15) - JPA实体继承
1. 实体继承映射的三种策略 #1. 整个类层次对应一张表 #2. 连接子类 #3. 每个具体类对应一张表 2. 使用抽象实体 3. 使用非实体父类 4. 重定义子类实体的外键列 ---------- ...
- 获得mysql内容,生成xml文件,另外,为了webservice发送
<xyt> <news id> <url></url> <title></title> </news> </x ...
- 采用xshell链路本地虚拟机Linux
昨天想安装在自己的机器看Linux.而使用xshell通路.但是这花了很长的时间,于xshell结束所有的提示"Could not connect to '192.168.54.100' ( ...
- ENode框架初始化
ENode框架初始化 前言 Conference案例是使用ENode框架来开发的.之前我没有介绍过ENode框架是如何启动的,以及启动时要注意的一些点,估计很多人对ENode框架的初始化这一块感觉很复 ...