在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. Path和ClassPath差异

    1.Path角色 Path它用于指定Java路径的命令,当我们想编译Java当需要使用的程序javac.exe并运行.class当文件需要使用java.exe,此时Path设置的路径就发生作用了.由于 ...

  2. [SignalR]一个简单的聊天室

    原文:[SignalR]一个简单的聊天室 1.说明 开发环境:Microsoft Visual Studio 2010 以及需要安装NuGet. 2.添加SignalR所需要的类库以及脚本文件: 3. ...

  3. 用命令行在github新建一个项目

    Github Repository API中说明了可以通过发送一个请求来认证,之后就能通过命令行自动新建远程仓库了. 认证 curl -u 'username' https://api.github. ...

  4. 基于NSIS脚本开发的安装程序制作软件:易量安装

    原文 基于NSIS脚本开发的安装程序制作软件:易量安装 前几天“萝卜”给我推荐了一款安装程序制作工具——易量安装. 易量安装是一款安装程序制作软件,基于著名的NSIS(Nullsoft Scripta ...

  5. SyntaxHighlighter代码高亮插件

    SyntaxHighlighter它是Google Code在一个开源项目,主要用于对代码着色页, 使用十分方便,效果也不错,并且差点儿支持常见的全部语言. 使用步骤: 一.下载并解压缩SyntaxH ...

  6. 【转】angularjs指令中的compile与link函数详解

    这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下   通常大家在 ...

  7. 乘法逆元...Orz

    最近打的几场比赛,都出现了有关逆元的题目,今天就整理了一下... 求乘法逆元的几种方法:http://www.cnblogs.com/james47/p/3871782.html 博文转载链接:htt ...

  8. PHP图片等比缩放,并添加Logo水印特定代码和盯

    <? php //PHP图片等比缩放,并添加Logo水印 --->百度 "美日汇" /** * 等比缩放函数(以保存的方式实现) * @param string $pi ...

  9. 用Maven整合SpringMVC+Spring+Hibernate 框架,实现简单的插入数据库数据功能

    一.搭建開始前的准备 1.我用的MyEclipse2014版,大家也能够用IDEA. 2.下载Tomcat(免安装解压包).MySQL(zip包下载地址 免安装解压包,优点就是双击启动,最后我会把ba ...

  10. 采用RedisLive监控Redis服务

    1.基础环境安装https://pypi.python.org/packages/source/b/backports.ssl_match_hostname/backports.ssl_match_h ...