AsyncTask引发的问题

时间:2021-08-31 16:42:36

http://blog.csdn.net/lichao3459/article/details/17712393

       最近写一个Android小应用,用到了AsyncTask发现一些问题,写篇日志避免日后再犯相同的错误,也给遇到与我

相同问题和疑惑的小伙伴们点思路。

AsyncTask的基本使用方法这里不再赘述,直接切入主题。

我用的SDK4.0,代码(片段)如下:

[java] view plain copy AsyncTask引发的问题AsyncTask引发的问题
  1. package com.lic.centerctrl;  
  2.   
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5. import java.util.concurrent.ExecutorService;  
  6. import java.util.concurrent.Executors;  
  7.   
  8. import com.lic.activity.ActivityInterFace;  
  9.   
  10. import android.app.Activity;  
  11. import android.app.Service;  
  12. import android.content.Context;  
  13. import android.content.Intent;  
  14. import android.os.AsyncTask;  
  15. import android.os.IBinder;  
  16.   
  17. public class MainService extends Service{  
  18.   
  19.     private static Task task;//当前执行任务  
  20.     private static Map<String, Activity> allActivitys = new HashMap<String, Activity>();//缓存activity集合  
  21.     private static ExecutorService exec = Executors.newSingleThreadExecutor();  
  22.       
  23.     @Override  
  24.     public void onStart(Intent intent, int startId) {  
  25.         super.onStart(intent, startId);  
  26.         MainAsyncTask asyncTask = new MainAsyncTask();  
  27.         //asyncTask.execute(task);  
  28.         //asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task);  
  29.         //asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);  
  30.         //asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task);  
  31.         asyncTask.executeOnExecutor(exec, task);  
  32.     }  
  33.   
  34.     private final class MainAsyncTask extends AsyncTask<Object, Integer, Object>{  
  35.         private Task task;  
  36.         @Override  
  37.         protected Object doInBackground(Object... params) {  
  38.             Object result = null;  
  39.             task = (Task)params[0];  
  40.             switch (task.getTaskID()) {  
  41.             case Task.TASK_USER_LOGIN:  
  42.                 try {  
  43.                     Thread.sleep(3000);  
  44.                     System.out.println("任务"+task.getTaskID()+" Thread id: "+Thread.currentThread().getId());  
  45.                 } catch (InterruptedException e) {  
  46.                     e.printStackTrace();  
  47.                 }  
  48.                 break;  
  49.             case 2:  
  50.                 System.out.println("任务"+task.getTaskID()+" Thread id: "+Thread.currentThread().getId());  
  51.                 break;  
  52.             }  
  53.             return result;  
  54.         }  
  55.   
  56.         @Override  
  57.         protected void onPostExecute(Object result) {  
  58.             super.onPostExecute(result);  
  59.             ActivityInterFace aif;  
  60.             switch (task.getTaskID()) {  
  61.             case Task.TASK_USER_LOGIN:  
  62.                 aif = (ActivityInterFace)allActivitys.get("LoginActivity");  
  63.                 aif.refresh(1, result);  
  64.                 break;  
  65.             case 2:  
  66.                 aif = (ActivityInterFace)allActivitys.get("LoginActivity");  
  67.                 aif.refresh(2, result);  
  68.                 break;  
  69.             default:  
  70.                 break;  
  71.             }  
  72.         }  
  73.           
  74.     }  
  75.       
  76.     /** 
  77.      * 添加新任务 
  78.      * @param task 
  79.      */  
  80.     public static void addTask(Context context, Task task) {  
  81.         MainService.task = task;  
  82.         context.startService(new Intent("mainService"));  
  83.     }  
  84.   
  85.     /** 
  86.      * 缓存activity 
  87.      * @param activity 
  88.      */  
  89.     public static void addActivity(Activity activity) {  
  90.         String path = activity.getClass().getName();  
  91.         String name = path.substring(path.lastIndexOf(".")+1);  
  92.         allActivitys.put(name, activity);  
  93.     }  
  94.   
  95.     @Override  
  96.     public IBinder onBind(Intent intent) {  
  97.         return null;  
  98.     }  
  99.   
  100. }  

    当我执行两次调用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);只有两个线程在执行

任务

AsyncTask引发的问题

当Executor类型为:private static ExecutorService exec = Executors.newSingleThreadExecutor();只有一个线程在执行任务

AsyncTask引发的问题