AsyncTask引发的问题
2013-12-31 13:44
274 查看
最近写一个android小应用,用到了AsyncTask发现一些问题,写篇日志避免日后再犯相同的错误,也给遇到与我
相同问题和疑惑的小伙伴们点思路。
AsyncTask的基本使用方法这里不再赘述,直接切入主题。
我用的SDK4.0,代码(片段)如下:
当我执行两次调用asyncTask.execute(task);时发现只有当第一次的任务完成后才执行下一下任务!!怎么回事?
AyncTask不是号称异步线程池吗?既然是线程池那么多任务执行时应该可以并发执行啊,至少两个任务可以并发执
行,以前看过一个视频,人家的就可以啊!纠结了一下午,通过查阅资料和自己的动手实验终于把问题搞明白了。
原来在SDK3.0以前的版本执行asyncTask.execute(task);时的确是多线程并发执行的,线程池大小为5,最大可大
128个,google在3.0以后的版本中做了修改,将asyncTask.execute(task);修改为了顺序执行,即只有当一个的实例
的任务完成后在执行下一个实例的任务。
那么怎么才能并发执行呢,很简单,3.0后新增了一个方法executeOnExecutor(Executor
exec, Object... params),
该方法接受2个参数,第一个是Executor,第二个是任务参数。第一个是线程池实例,google为我们预定义了两种:
第一种是AsyncTask.SERIAL_EXECUTOR,第二种是AsyncTask.THREAD_POOL_EXECUTOR,顾名思义,第一
种其实就像3.0以后的execute方法,是顺序执行的。第二种就是3.0以前的execute方法,是可以并发执行的。我们直
接用asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);就可以多任务并发执行了。
既然executeOnExecutor第一个参数是Executor,那么我们可以自定义Executor吗?当然可以,Executor主要由四
种类型newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor
(具体使用解析可以看我上一篇文章点击打开链接),可是当我这样使用
asyncTask.executeOnExecutor(Executors.newFixedThreadPool(1), task);或者
asyncTask.executeOnExecutor(Executors.newSingleThreadExecutor, task);并没有像我想象的与
asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task);那样是单线程顺序执行,而是像
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);是多线程并发执行的,我不是
已经规定newFixedThreadPool的线程池数量是1或者是newSingleThreadExecutor单线程了么!怎么回事呢?原来程
序在每次调用asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task)时会获取一个新的Executor对
象,这个对象内的线程只执行对应的task,所以无论哪种情况每个task都有一个新的线程来执行,即并发执行。
知道原因就好办了,我们定义个一全局静态变量
private static ExecutorService exec = Executors.newSingleThreadExecutor();程序在每次调用
asyncTask.executeOnExecutor(exec, task);时是使用的同一个Executor,执行效果如下:
当Executor类型为:private static ExecutorService exec = Executors.newFixedThreadPool(2);只有两个线程在执行
任务
当Executor类型为:private static ExecutorService exec = Executors.newSingleThreadExecutor();只有一个线程在执行任务
相同问题和疑惑的小伙伴们点思路。
AsyncTask的基本使用方法这里不再赘述,直接切入主题。
我用的SDK4.0,代码(片段)如下:
package com.lic.centerctrl; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.lic.activity.ActivityInterFace; import android.app.Activity; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.AsyncTask; import android.os.IBinder; public class MainService extends Service{ private static Task task;//当前执行任务 private static Map<String, Activity> allActivitys = new HashMap<String, Activity>();//缓存activity集合 private static ExecutorService exec = Executors.newSingleThreadExecutor(); @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); MainAsyncTask asyncTask = new MainAsyncTask(); //asyncTask.execute(task); //asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task); //asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task); //asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task); asyncTask.executeOnExecutor(exec, task); } private final class MainAsyncTask extends AsyncTask<Object, Integer, Object>{ private Task task; @Override protected Object doInBackground(Object... params) { Object result = null; task = (Task)params[0]; switch (task.getTaskID()) { case Task.TASK_USER_LOGIN: try { Thread.sleep(3000); System.out.println("任务"+task.getTaskID()+" Thread id: "+Thread.currentThread().getId()); } catch (InterruptedException e) { e.printStackTrace(); } break; case 2: System.out.println("任务"+task.getTaskID()+" Thread id: "+Thread.currentThread().getId()); break; } return result; } @Override protected void onPostExecute(Object result) { super.onPostExecute(result); ActivityInterFace aif; switch (task.getTaskID()) { case Task.TASK_USER_LOGIN: aif = (ActivityInterFace)allActivitys.get("LoginActivity"); aif.refresh(1, result); break; case 2: aif = (ActivityInterFace)allActivitys.get("LoginActivity"); aif.refresh(2, result); break; default: break; } } } /** * 添加新任务 * @param task */ public static void addTask(Context context, Task task) { MainService.task = task; context.startService(new Intent("mainService")); } /** * 缓存activity * @param activity */ public static void addActivity(Activity activity) { String path = activity.getClass().getName(); String name = path.substring(path.lastIndexOf(".")+1); allActivitys.put(name, activity); } @Override public IBinder onBind(Intent intent) { return null; } }
当我执行两次调用asyncTask.execute(task);时发现只有当第一次的任务完成后才执行下一下任务!!怎么回事?
AyncTask不是号称异步线程池吗?既然是线程池那么多任务执行时应该可以并发执行啊,至少两个任务可以并发执
行,以前看过一个视频,人家的就可以啊!纠结了一下午,通过查阅资料和自己的动手实验终于把问题搞明白了。
原来在SDK3.0以前的版本执行asyncTask.execute(task);时的确是多线程并发执行的,线程池大小为5,最大可大
128个,google在3.0以后的版本中做了修改,将asyncTask.execute(task);修改为了顺序执行,即只有当一个的实例
的任务完成后在执行下一个实例的任务。
那么怎么才能并发执行呢,很简单,3.0后新增了一个方法executeOnExecutor(Executor
exec, Object... params),
该方法接受2个参数,第一个是Executor,第二个是任务参数。第一个是线程池实例,google为我们预定义了两种:
第一种是AsyncTask.SERIAL_EXECUTOR,第二种是AsyncTask.THREAD_POOL_EXECUTOR,顾名思义,第一
种其实就像3.0以后的execute方法,是顺序执行的。第二种就是3.0以前的execute方法,是可以并发执行的。我们直
接用asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);就可以多任务并发执行了。
既然executeOnExecutor第一个参数是Executor,那么我们可以自定义Executor吗?当然可以,Executor主要由四
种类型newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor
(具体使用解析可以看我上一篇文章点击打开链接),可是当我这样使用
asyncTask.executeOnExecutor(Executors.newFixedThreadPool(1), task);或者
asyncTask.executeOnExecutor(Executors.newSingleThreadExecutor, task);并没有像我想象的与
asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task);那样是单线程顺序执行,而是像
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);是多线程并发执行的,我不是
已经规定newFixedThreadPool的线程池数量是1或者是newSingleThreadExecutor单线程了么!怎么回事呢?原来程
序在每次调用asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task)时会获取一个新的Executor对
象,这个对象内的线程只执行对应的task,所以无论哪种情况每个task都有一个新的线程来执行,即并发执行。
知道原因就好办了,我们定义个一全局静态变量
private static ExecutorService exec = Executors.newSingleThreadExecutor();程序在每次调用
asyncTask.executeOnExecutor(exec, task);时是使用的同一个Executor,执行效果如下:
当Executor类型为:private static ExecutorService exec = Executors.newFixedThreadPool(2);只有两个线程在执行
任务
当Executor类型为:private static ExecutorService exec = Executors.newSingleThreadExecutor();只有一个线程在执行任务
相关文章推荐
- AsyncTask引发的问题
- AsyncTask引发的问题
- AsyncTask引发的一个问题:doInBackground()未及时执行
- AsyncTask引发的问题
- mysql - 为magento性能测试修改innodb的innodb_buffer_pool_size而引发的问题
- MFC中SDI,视类继承于CFormView引发的相关问题
- Asynctask onPostExecute未执行的问题分析
- 关于项目导入别人jar包引发的问题总结
- C/C++——一个因为unsigned引发的大问题
- jdk版本不同引发的怪异问题(jdk1.5与jdk1.6之间)
- 由android:process引发的内存限制的问题
- UTF-8编码引发的页面奇怪问题
- 配置文件出现BOM头(文件编码改变)引发的问题
- [MySQL优化案例]系列 — 典型性索引引发CPU负载飙升问题
- swiper loop:true引发的问题及解决方法
- android studio 图片资源的放置位置和容易引发的问题
- C++内存泄漏——C++中动态内存分配引发问题的解决方案(2)
- 测试环境归档日志满引发的各种问题
- "SQL1218N 在缓冲池 4096 中当前没有任何页面可用"问题的解决(由于隐藏的buffer引发的血案)
- AppiumDriver升级到2.0.0版本引发的问题--Cannot instantiate the type AppiumDriver