博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android AsyncTask内部线程池异步执行任务机制简要分析
阅读量:5036 次
发布时间:2019-06-12

本文共 3928 字,大约阅读时间需要 13 分钟。

如下分析针对的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
{ @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)

  

转载于:https://www.cnblogs.com/sphere/p/7815397.html

你可能感兴趣的文章
MySQL 命令总结
查看>>
(算法)精确表示小数
查看>>
python16_day22【cmdb注释】
查看>>
关于监听器那些让人头疼的事
查看>>
rem
查看>>
莫比乌斯反演总结
查看>>
10天学安卓-第二天
查看>>
vi撤销 恢复 (vi学习)
查看>>
bzoj3261
查看>>
HTML中哪些标签的值会被提交到服务器呢?
查看>>
sublime Text3
查看>>
创建表的时候创建索引
查看>>
关于Windows10升级10586之后微软小娜无法打开的问题
查看>>
Strom的trident小例子
查看>>
iOS开发数据库篇—FMDB简单介绍
查看>>
rootkit后门检查工具RKHunter
查看>>
Mysql 远程访问控制 -- 10038 问题的解决
查看>>
springcloud之feign中使用Hystrix熔断器时的报错解决办法
查看>>
maven3常用命令、java项目搭建、web项目搭建详细图解(转)
查看>>
codevs 1200 同余方程 (Extend_Eulid)
查看>>