【问题标题】:Asynctask parallel executionAsynctask 并行执行
【发布时间】:2017-04-01 13:44:11
【问题描述】:

在应用程序启动时,我正在进行网络调用(resttemplate Get 调用)以获取数据。

场景是这样的,

1)返回令牌列表(ID)的父调用

2)一旦我得到了令牌(Id)列表,我会遍历它,对每个令牌(Id)进行网络调用以获取数据。

我这样做的目的:

1)我已使用 Intent 服务进行父网络调用以获取列表令牌(ID)。

2)一旦我得到列表令牌(Id's),我就启动了我的 AsyncTask executeOnExecutor,通过构造函数将令牌列表(ID's)传递给 asynctask 并启动 AsyncTask 执行器。 像这样的,

MyAsyncExecutorTask executorTask = new MyAsyncExecutorTask(List<Integer> of tokens);
executorTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,(Void[]) null);

而在 MyAsyncExecutorTask 这就是我正在做的事情。

 protected Void doInBackground(Void...params) {

    //Settimg max priority
    Thread.currentThread().setPriority(Thread.MAX_PRIORITY);

    for (int i = 0; i < scheduleList.size(); i++) { 
       ScheduleImpl scheduleImpl = new ScheduleImpl();
        //Making network call to get data using token
        scheduleImpl.getData(scheduleList(i));
    }

 }

它应该正常工作。

我的疑问或问题是:

1) 我是否以正确的方式使用 Async executeOnExecuter()(我想进行并行网络调用)。从 AsyncTask execute() 切换到 Async executeOnExecuter() 后,我没有看到任何巨大的性能提升。

2)如何检查有多少工作线程正在运行。

【问题讨论】:

    标签: java android multithreading android-asynctask threadpoolexecutor


    【解决方案1】:

    你可以这样:

    AsyncTaskGetTokens.java

    public class AsyncTaskGetTokens extends AsyncTask<Void,Integer, List<Integer>> {
    
        private ProgressDialog pd;
        private Context context;
        private String dataURL;
    
        public AsyncTaskGetTokens (Context context, Integer token)
        {
            this.act = act;
            this.token = token;
        }
    
        protected void onPreExecute()
        {
            this.pd = ProgressDialog.show(context, "", "");
        }
    
        protected Integer doInBackground(Void... arg0) {
            List<Integer> tokenList = new List<Integer>();
            //get token list from URL here
            return tokenList;
        }
    
        protected void onPostExecute(List<Integer> tokenList)
        {
            this.pd.dismiss();
            AsyncTaskGetData.tokensDownloading = new List<AsyncTaskGetData>();
            foreach(Integer token : tokenList)
            {
                AsyncTaskGetData.tokensDownloading.add(new AsyncTaskGetData(context, token); // here you create a list with all the tokens that will be downloaded
            }
            foreach(AsyncTaskGetData asynctask : AsyncTaskGetData.tokensDownloading)
            {
                asynctask.execute(); // here you will start downloading the data from each token
            }
        }
    
    }
    

    AsyncTaskGetData.java

    public class AsyncTaskGetData extends AsyncTask<Void,Integer, Data> {
    
        public static List<AsyncTaskGetData> tokensDownloading;
    
        private ProgressDialog pd;
        private Context context;
        private Integer token;
    
        public AsyncTaskGetData (Context context, Integer token)
        {
            this.context = context;
            this.token = token;
        }
    
        protected void onPreExecute()
        {
            this.pd = ProgressDialog.show(context, "", "");
        }
    
        protected Data doInBackground(Void... arg0) {
            Data data = getDataFromURL(token);
            return data;
        }
    
        protected void onPostExecute(Data data)
        {
            //show data here
            this.pd.dismiss();
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      1)我是否以正确的方式使用 Async executeOnExecuter()(我想进行并行网络调用)。从 AsyncTask execute() 切换到 Async executeOnExecuter() 后,我没有看到任何巨大的性能提升。

      来自 Android 文档

      执行

      使用指定参数执行任务。任务返回自身 (this),以便调用者可以保留对它的引用。

      注意:此函数根据平台版本将任务安排在单个后台线程或线程池的队列中。首次引入时,AsyncTask 是在单个后台线程上串行执行的。从 DONUT 开始,这被更改为允许多个任务并行运行的线程池。启动 HONEYCOMB,任务恢复为单线程执行,避免并行执行导致的常见应用错误

      executeOnExecuter

      使用指定参数执行任务。任务返回自身 (this),以便调用者可以保留对它的引用。

      此方法通常与 THREAD_POOL_EXECUTOR 一起使用,以允许多个任务在 AsyncTask 管理的线程池上并行运行,但是您也可以使用自己的 Executor 来进行自定义行为。

      警告:允许多个任务从线程池并行运行通常不是人们想要的,因为它们的操作顺序没有定义。例如,如果这些任务用于修改任何共同的状态(例如由于单击按钮而写入文件),则无法保证修改的顺序。如果不仔细工作,在极少数情况下,较旧版本的数据可能会覆盖较新版本的数据,从而导致难以理解的数据丢失和稳定性问题。此类更改最好​​按顺序执行;为了保证无论平台版本如何都可以序列化此类工作,您可以将此函数与 SERIAL_EXECUTOR 一起使用。

      问题不一定与性能改进有关。当您作为 executeOnExecuter 运行时,无法保证调用将按照您创建它们的顺序返回。执行方法将在队列中为单个后台线程调度任务。

      2)如何检查有多少工作线程正在运行。

      你有能力定义你自己的工作队列,所以如果问题是你可以运行多少线程,那么请参考这篇文章Android AsyncTask threads limits?

      我不确定是否有一种简单的方法可以检查当前运行的计数。如果有我相信有人会对此发表评论。但是您可以保留对每个任务的引用并检查其状态。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多