在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默认的单线程分析的更多相关文章

  1. IIS6(Win2003) 使用.net 4.0 后,默认文档失效解决方案。

    IIS6(Win2003) 使用.net framework 4.0 后,默认文档失效解决方案. 用.net framework 4.0 开发的WEB项目,但放到iis6 中无法使用默认文档,状况如下 ...

  2. android 4.0后不允许屏蔽掉home键

    屏蔽home键的方法 // 屏蔽掉Home键 public void onAttachedToWindow() { this.getWindow().setType(WindowManager.Lay ...

  3. Android Studio安装后配置默认新工程目录以及.gradle,.android,.m2和system,config目录

    关于在哪里设置:以下所有设置都是在没有打开工程的前提下设置的, Configure > Settings 如图: 不要使用 Configure > Project Defaults> ...

  4. 转 Android 4.0后,自定义Title报错 You cannot combine custom titles with other title feature

      自定义Titlebar时为了避免冲突 需要修改:AndroidManifest.xml android:theme="@style/mystyle" styles.xml文件中 ...

  5. Android 6.0 M userdebug版本执行adb remount失败

    [FAQ18076]Android 6.0 M版本默认会打开system verified boot,即在userdebug和user版本会把system映射到dm-0设备,然后再挂载.挂载前会检查s ...

  6. Android 5.0之后屏幕截图的方法

    截图的几种方法 Android获取屏幕截图主要有以下三种方法 1.通过view.getDrawingCache()获取指定View的绘制缓存来实现截屏. 这种方式Android 5.0之前也可以,且不 ...

  7. Android权限管理之RxPermission解决Android 6.0 适配问题

    前言: 上篇重点学习了Android 6.0的运行时权限,今天还是围绕着Android 6.0权限适配来总结学习,这里主要介绍一下我们公司解决Android 6.0权限适配的方案:RxJava+RxP ...

  8. Android 5.0之前屏幕截图的方法

    截图的几种方法 Android获取屏幕截图主要有以下三种方法 1.通过view.getDrawingCache()获取指定View的绘制缓存来实现截屏. 这种方式Android 5.0之前也可以,且不 ...

  9. Android 9.0适配遇到的问题1

    文章同步自javaexception 本周在适配Android 9.0,过程中碰到了小问题 问题1: SSL handshake timed out 解决办法: Android 9.0 开始,默认不允 ...

随机推荐

  1. unity3D实际的原始视频游戏开发系列讲座10它《战斗:外来入侵》在第一季度游戏开发

    解说文件夹 <保卫战:异形入侵>游戏开发 第一讲   游戏演示和资源的介绍 第二讲  "异形"怪物的实现 第三讲  "异形"怪物生命值的体现 第四讲 ...

  2. android学习记录(三)百度地图错误---只有一个电话显示帧,没有地图内容。

    安卓开发新手百度地图,刚开始碰到一个问题,没有地图信息,还有就是它只有一帧. 如图所示: 上网寻找说是key的问题,然后又一次申请.还是不行. 最后再次看了自己的Manifest文件,发现自己的< ...

  3. InstallShield自定义安装界面

    原文:InstallShield自定义安装界面 版权声明: 可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息. 前言: 对于一些InstallShield用户或企业,对于安装包界面除了 ...

  4. JavaScript 实现Map效果

    var map = {}; // 类似:Map map = new HashMap(); map[key] = value; // 类似:map.put(key, value); var value ...

  5. Git常用命令(转)

    目前开发的新项目使用的版本控制工具基本用的都是Git,老项目用的还是Svn,网上Git资源也很多,多而杂.我整理了一份关于Git的学习资料,希望能帮助到正在学习Git的同学. 一. Git 命令初识 ...

  6. js中frame的操作问题

    这里以图为例,在这里把frame之间的互相操作简单列为:1变量2方法3页面之间元素的互相获取. A  首先从 父(frameABC)------->子(frameA,frameB,frameC) ...

  7. AspNetPager常用属性及一些样式

    AlwaysShow 总是显示分页控件,即使要分页的数据只有一页 AlwaysShowFirsLastPageNumbr 是否总是显示第一页和最后一页数字页索引按钮 BackImageUrl 面板的背 ...

  8. IOS的UITextField,UIButton,UIWebView它描述的一些属性和IOS提示图像资源

    有时UI要开发的资源与实际frame不符.这一次,我们要绘制图片 UIImage* image = [[UIImage imageNamed:@"text_field_bg.png" ...

  9. [ACM] POJ 3061 Subsequence (仿真足)

    Subsequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8403   Accepted: 3264 Descr ...

  10. 使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置)

    原文:使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置) 在上一篇中说到了Silverlight下的Socket通信,在最后的时候说到本篇将会结合地图. ...