网站制作价格浦东医院网站建设
web/
2025/10/7 1:06:12/
文章来源:
网站制作价格,浦东医院网站建设,企业网站keywords最多几个,企业网站设计调查问卷Android AsyncTask两种线程池分析和总结(一) 前言在android AsyncTask里面有两种线程池供我们调用1#xff0e; THREAD_POOL_EXECUTOR, 异步线程池2#xff0e; SERIAL_EXECUTOR#xff0c;同步线程池正如上面名称描述的那样#xff0c;一个是异步线程池#xff…Android AsyncTask两种线程池分析和总结(一) 前言在android AsyncTask里面有两种线程池供我们调用1 THREAD_POOL_EXECUTOR, 异步线程池2 SERIAL_EXECUTOR同步线程池正如上面名称描述的那样一个是异步线程池多个任务在线程池中并发执行还有一个是同步执行的。默认的话直接调用execute的话是使用SERIAL_EXECUTOR下面的话会用源代码的方式来说明这两种线程池的作用和注意事项。(二) THREAD_POOL_EXECUTOR用法举例 private static int produceTaskMaxNumber 500;
02public void dotask(){
03for (int i 1; i produceTaskMaxNumber; i){
04// 产生一个任务并将其加入到线程池
05String task task i;
06Log.d(Sandy, put task);
07MyAsyncTask asynct new MyAsyncTask(task);
08asynct.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 0);
09}
10}
1112static class MyAsyncTask extends AsyncTaskInteger, Integer, Integer{
13private static int consumeTaskSleepTime 2000;
14// 保存任务所需要的数据
15private Object threadPoolTaskData;
16public MyAsyncTask(String s){
17threadPoolTaskData s;
18}
19a hrefhttp://home.51cto.com/index.php?s/space/5017954 target_blankOverride/a
20protected Integer doInBackground(Integer... arg0) {
21Log.d(Sandy, start .. threadPoolTaskData
22 thread id: Thread.currentThread().getId()
23 thread name: Thread.currentThread().getName());
24try {
25// //便于观察等待一段时间
26Thread.sleep(consumeTaskSleepTime);
27}
28catch (Exception e) {
29Log.d(Sandy, , e);
30}
31threadPoolTaskData null;
32return 0;
33}
34}2 使用方法比较简单首先创建一个继承自AsyncTask的MyAsyncTask类然后调用MyAsyncTask asynct new MyAsyncTask(task);
2asynct.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 0);就可以了。3 上面代码执行的时候会出错导致程序异常终止如下图就是因为我们尝试添加500个task到AsyncTask.THREAD_POOL_EXECUTOR线程池中但是它的核心线程是5队列容量是128最大线程数是9。 所以抛出了这个异常。 那么接下来的话我们会去分析这个异常怎么出来的。 (三) THREAD_POOL_EXECUTOR代码分析 从AsyncTask.THREAD_POOL_EXECUTOR的定义开始分析 1. 代码路径 frameworks\base\core\java\android\os\AsyncTask.java 代码 private static final int CPU_COUNT Runtime.getRuntime().availableProcessors();
02private static final int CORE_POOL_SIZE CPU_COUNT 1;
03private static final int MAXIMUM_POOL_SIZE CPU_COUNT * 2 1;
04private static final int KEEP_ALIVE 1;
0506....
07/**
08* An {link Executor} that can be used to execute tasks in parallel.
09*/
10public static final Executor THREAD_POOL_EXECUTOR
11 new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
12TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);它的几个参数CORE_POOL_SIZE, MAXIMUN_POOL_SIZE, 都是根据当前手机的处理器数量进行动态定义的。那么继续往下面看看这几个参数传进去后是什么意思。2. 代码路径\libcore\luni\src\main\java\java\util\concurrent\ThreadPoolExecutor.java代码public ThreadPoolExecutor(int corePoolSize,
02int maximumPoolSize,
03long keepAliveTime,
04TimeUnit unit,
05BlockingQueueRunnable workQueue,
06ThreadFactory threadFactory,
07RejectedExecutionHandler handler) {
08if (corePoolSize 0 ||
09maximumPoolSize 0 ||
10maximumPoolSize corePoolSize ||
11keepAliveTime 0)
12throw new IllegalArgumentException();
13if (workQueue null || threadFactory null || handler null)
14throw new NullPointerException();
15this.corePoolSize corePoolSize;
16this.maximumPoolSize maximumPoolSize;
17this.workQueue workQueue;
18this.keepAliveTime unit.toNanos(keepAliveTime);
19this.threadFactory threadFactory;
20this.handler handler;
21}
2223/**
24* The default rejected execution handler
25*/
26private static final RejectedExecutionHandler defaultHandler
27new AbortPolicy();这是ThreadPoolExecutor的构造函数首先需要明白的是这几个参数的含义A corePoolSize 线程池维护线程的最少数量B maximumPoolSize线程池维护线程的最大数量C keepAliveTime 线程池维护线程所允许的空闲时间D unit 线程池维护线程所允许的空闲时间的单位E workQueue 线程池所使用的缓冲队列F handler 线程池对拒绝任务的处理策略当一个任务通过asynct.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 0)方法欲添加到线程池时如果此时线程池中的数量小于corePoolSize即使线程池中的线程都处于空闲状态也要创建新的线程来处理被添加的任务。如果此时线程池中的数量等于 corePoolSize但是缓冲队列 workQueue未满那么任务被放入缓冲队列。如果此时线程池中的数量大于corePoolSize缓冲队列workQueue满并且线程池中的数量小于maximumPoolSize建新的线程来处理被添加的任务。如果此时线程池中的数量大于corePoolSize缓冲队列workQueue满并且线程池中的数量等于maximumPoolSize那么通过 handler所指定的策略来处理此任务。也就是处理任务的优先级为核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize如果三者都满了使用handler处理被拒绝的任务。当线程池中的线程数量大于 corePoolSize时如果某线程空闲时间超过keepAliveTime线程将被终止。这样线程池可以动态的调整池中的线程数。unit可选的参数为java.util.concurrent.TimeUnit中的几个静态属性NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。workQueue是BlockQueue的子类ArrayBlockingQueue,DelayQueuehandler有四个选择(这不是android的Handler)ThreadPoolExecutor.AbortPolicy() – 这个也是AsyncTask.THREAD_POOL_EXECUTOR使用的抛出java.util.concurrent.RejectedExecutionException异常ThreadPoolExecutor.CallerRunsPolicy()重试添加当前的任务他会自动重复调用execute()方法ThreadPoolExecutor.DiscardOldestPolicy()抛弃旧的任务ThreadPoolExecutor.DiscardPolicy()抛弃当前的任务所以正是我们的AsyncTask.THREAD_POOL_EXECUTOR使用了AbortPolicy()类型的handler所以才会抛出异常..那么在把任务添加到AsyncTask.THREAD_POOL_EXECUTOR之后下面的工作就是由这个线程池来调度线程执行任务了。(四) AsyncTask. SERIAL_EXECUTOR1. 使用方法AsyncTask. SERIAL_EXECUTOR的使用方法和Async.THREAD_POOL_EXECUTOR差不多。不过正如前面所说它是默认的Executor所以可以直接调用所以可以有两种调用方法。1a. asynct.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, 0); 2b. asynct.execute(0); 效果是一样的2执行流程代码路径:frameworks\base\core\java\android\os\AsyncTask.java代码01public final AsyncTaskParams, Progress, Result executeOnExecutor(Executor exec, 02 Params... params) { 03 ... 04 exec.execute(mFuture); 05 .... 06} 07 08private static class SerialExecutor implements Executor { 09 final ArrayDequeRunnable mTasks new ArrayDequeRunnable(); 10 Runnable mActive; 11 public synchronized void execute(final Runnable r) { 12 mTasks.offer(new Runnable() { 13 public void run() { 14 try { 15 r.run(); 16 } finally { 17 scheduleNext(); 18 } 19 } 20 }); 21 if (mActive null) { 22 scheduleNext(); 23 } 24 } 25 26 protected synchronized void scheduleNext() { 27 if ((mActive mTasks.poll()) ! null) { 28 THREAD_POOL_EXECUTOR.execute(mActive); 29 } 30 } 31 } 嗯它会调用到SerialExecutor.execute(Runnable r)方法在这个方法里面它首先把任务放到mTasks这个集合里面然后判断mActivie是否为空,再调用scheduleNext ()方法。mActivie为null的意思是当前没有任务在执行如果mActivie!null那么说明当前有任务正在执行那么只要把任务添加到mTasks里面即可。因为任务执行完毕后会再次调用scheduleNext()方法的就是finally {scheduleNext();}这样就形成了一种链状调用结构只要mTasks里面还有任务就会不断逐一调用如果后面有任务进来就只要添加到mTasks里面即可。同时不知道大家注意到没有这两个方法都是synchronized的这样就保证了多线程之间调度问题。否则肯定会出现问题的至于什么问题大家想想就能明白。4 继续分析scheduleNext()方法这个方法首先把mTasks里面的数据取一个出来然后调用THREAD_POOL_EXECUTOR.execute(mActive);我晕这不就是上面一直在分析的AsyncTask.THREAD_POOL_EXECUTOR么好吧原来AsyncTask.THREAD_POOL_EXECUTOR和AsyncTask.SERIAL_EXECUTOR的区别就是SERIAL_EXECUTOR在THREAD_POOL_EXECUTOR的基础上添加了一个mTasks的集合来保证任务顺序执行而已...(五) 总结说了这么多总结下1. AsyncTask里面有THREAD_POOL_EXECUTOR和SERIAL_EXECUTOR两种方式来异步执行任务THREAD_POOL_EXECUTOR是异步的而SERIAL_EXECUTOR任务是顺序执行的。2. THREAD_POOL_EXECUTOR如果添加的任务过多没有及时处理的话会导致程序崩溃它的队列size是128它的调度规则是核心池大小队列大小以及最大线程数和异常处理Handler来决定的。3. SERIAL_EXECUTOR本质是在THREAD_POOL_EXECUTOR的基础上添加一个mTasks的集合来保证任务的顺序执行。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/88197.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!