如下分析针对的API 25的AsyncTask的源码:

  使用AsyncTask如果是调用execute方法则是同步执行任务,想要异步执行任务可以直接调用executeOnExecutor方法,多数情况下我们会使用AsyncTask内部静态的线程池,

THREAD_POOL_EXECUTOR,这里并不是要分析AsyncTask内部的流程,而是简单介绍下线程池的工作流程。可以看到THREAD_POOL_EXECUTOR的配置如下:

new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

简单介绍下ThreadPoolExecutor的几个参数:

  int corePoolSize,核心线程数,可以一直存活在线程池中,除非设置了allowCoreThreadTimeOut,即允许核心线程超时。 int maximumPoolSize, 线程池中允许的最大线程数。long keepAliveTime,  当线程池中的线程数超过核心线程数时,非核心线程在等待keepAliveTime时间终止,即非核心线程空等待任务(存活时间)的超时时间是keepAliveTime,TimeUnit unit, 超时时间的单位,BlockingQueue<Runnable> workQueue, 缓冲任务队列,ThreadFactory threadFactory 用于创建新线程,可以设置线程优先级等。具体可以查看API文档或java.util.concurrent.ThreadPoolExecutor的源码

具体来说,当一个任务被提交到线程池后,会先看核心线程是否都有任务正在执行,如果核心线程有空闲,则核心线程执行任务,否则将任务添加到缓冲队列中,待核心线程执行完任务后取缓冲队列中的任务执行。如果任务较多,缓冲队列添加满了,且还有任务提交,那么会启动非核心线程执行任务,如果非核心线程数也全部都在工作,即线程池中的线程数达到了最大线程数 MAXIMUM_POOL_SIZE的限制时,再提交任务到线程池则会报拒绝执行任务的异常 java.util.concurrent.RejectedExecutionException

  可以用如下代码简单测试下:

  先自定义一个AsyncTask

  

static int index = 1;
static class MyAsyncTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(2000);
return null;
} @Override
protected void onPostExecute(Void aVoid) {
Log.d(this.getClass().getSimpleName(), "task#" + index + " had executed.");
index++;
}
}

  这里为了能够看到如上表述的过程,在doInbackground中让线程睡眠2秒,并对每个AsyncTask输出执行完成的log,附带index标识是第几个。

  然后提交任务到线程池中

        int CPU_COUNT = Runtime.getRuntime().availableProcessors();
int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; int taskMaxCounts = MAXIMUM_POOL_SIZE + 128;
for (int i = 0 ; i < taskMaxCounts; i++ ) {
new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void)null);
}

  最大可同时容纳的任务数即: MAXIMUM_POOL_SIZE + 128 (缓冲队列任务数), 针对API25的版本, 如何CPU是4核心,那么最大任务数是 4 * 2 + 1 + 128 = 137 .

  当线程池中线程都有任务正在执行且缓冲队列已满时,继续往线程池中提交任务则会报异常,这里可以将taskMaxCounts 改为 MAXIMUM_POOL_SIZE + 129,

  再次运行程序则会看到异常log信息

  

 FATAL EXCEPTION: main
Process: com.aquarius.test, PID: 22425
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.aquarius.test/com.http.study.demo.VolleyActivity}: java.util.concurrent.RejectedExecutionException: Task android.os.AsyncTask$3@75bef95 rejected from java.util.concurrent.ThreadPoolExecutor@76298aa[Running, pool size = 9, active threads = 9, queued tasks = 128, completed tasks = 0]
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2509)
at android.app.ActivityThread.access$1000(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1373)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:5524)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:740)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:630)
Caused by: java.util.concurrent.RejectedExecutionException: Task android.os.AsyncTask$3@75bef95 rejected from java.util.concurrent.ThreadPoolExecutor@76298aa[Running, pool size = 9, active threads = 9, queued tasks = 128, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2014)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:794)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1340)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:607)

  

Android AsyncTask内部线程池异步执行任务机制简要分析的更多相关文章

  1. Android开发之线程池使用总结

    线程池算是Android开发中非常常用的一个东西了,只要涉及到线程的地方,大多数情况下都会涉及到线程池.Android开发中线程池的使用和Java中线程池的使用基本一致.那么今天我想来总结一下Andr ...

  2. android中的线程池学习笔记

    阅读书籍: Android开发艺术探索 Android开发进阶从小工到专家 对线程池原理的简单理解: 创建多个线程并且进行管理,提交的任务会被线程池指派给其中的线程进行执行,通过线程池的统一调度和管理 ...

  3. Android中的线程池

    在Android中,主线程不能执行耗时的操作,否则可能会导致ANR.那么,耗时操作应该在其它线程中执行.线程的创建和销毁都会有性能开销,创建过多的线程也会由于互相抢占系统资源而导致阻塞的现象.这个时候 ...

  4. Android下基于线程池的网络访问基础框架

    引言 现在的Android开发很多都使用Volley.OkHttp.Retrofit等框架,这些框架固然有优秀的地方(以后会写代码学习分享),但是我们今天介绍一种基于Java线程池的网络访问框架. 实 ...

  5. 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法

    [源码下载] 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法 作者:webabcd 介绍重新想象 Wi ...

  6. 戏(细)说Executor框架线程池任务执行全过程(上)

    一.前言 1.5后引入的Executor框架的最大优点是把任务的提交和执行解耦.要执行任务的人只需把Task描述清楚,然后提交即可.这个Task是怎么被执行的,被谁执行的,什么时候执行的,提交的人就不 ...

  7. C# -- 使用线程池 ThreadPool 执行多线程任务

    C# -- 使用线程池 ThreadPool 执行多线程任务 1. 使用线程池 class Program { static void Main(string[] args) { WaitCallba ...

  8. java并发编程(四) 线程池 & 任务执行、终止源码分析

    参考文档 线程池任务执行全过程:https://blog.csdn.net/wojiaolinaaa/article/details/51345789 线程池中断:https://www.cnblog ...

  9. ForkJoinPool线程池--分支执行

    import java.util.ArrayList; import java.util.concurrent.ExecutionException; import java.util.concurr ...

随机推荐

  1. (译)通过 HTML、JS 和 Electron 创建你的第一个桌面应用

    原文:Creating Your First Desktop App With HTML, JS and Electron 作者:Danny Markov 近年来 web 应用变得越来越强大,但是桌面 ...

  2. ESLint可共享配置发布,团队自定义ESLint规则新鲜出炉

    ESLint于2013年6月份推出,至今4个年头,最新版本v4.8.0.它是目前主流的用于Javascript和JSX代码规范检查的利器,很多大公司比如Airbnb和Google均有一套自己的Java ...

  3. 自适应 Tab 宽度可以滑动文字逐渐变色的 TabLayout(仿今日头条顶部导航)

    TabLayout相信大家都用过,2015年Google大会上发布了新的Android Support Design库里面包含了很多新的控件,其中就包含TabLayout,它可以配合ViewPager ...

  4. ZOJ2334 Monkey King 并查集 STL

    题意:两家原始人(猴)打交道后成为一家猴,打交道时两家分别派出最帅的两位猴子,颜值各自减半,问每次打交道后新家族最帅的猴子的颜值.当然,已经是一家子就没有必要打交道了,因为没有猴希望颜值降低,毕竟还得 ...

  5. Java 继承、抽象、接口

    一.继承 1. 概述 继承是面向对象的重要特征之一,当多个类中存在相同的属性和行为时,将这些内容抽取到单独一个类中,那多个类中无需再定义这些属性和行为,只需继承那个单独的类即可. 单独的类称为父类或超 ...

  6. 让asp.net网站支持多语言,使用资源文件

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="test.aspx.cs&quo ...

  7. [Python]Codecombat攻略之远边的森林Forest(1-40关)

    首页:https://cn.codecombat.com/play语言:Python 第二界面:远边的森林Forest(40关)时间:2-6小时内容:if/else.关系操作符.对象属性.处理输入网页 ...

  8. Hadoop(七)HDFS容错机制详解

    前言 HDFS(Hadoop Distributed File System)是一个分布式文件系统.它具有高容错性并提供了高吞吐量的数据访问,非常适合大规模数据集上的应用,它提供了一个高度容错性和高吞 ...

  9. Java简单工厂模式以及来自lambda的优化

    前言    设计模式是软件工程中一些问题的统一解决方案的模型,它的出现是为了解决一些普遍存在的,却不能被语言特性直接解决的问题,随着软件工程的发展,设计模式也会不断的进行更新,本文介绍的是经典设计模式 ...

  10. 表单处理的方案与注意事项(servlet)

    摘要 表单是后端程序员用的与接触最多的,我这里例举了常用处理办法,与注意事项 sevlet处理代码 package myform; import java.io.IOException; import ...