ASyncTasks阻止其他人

时间:2012-08-28 22:55:25

标签: android multithreading thread-safety android-asynctask

我有2个ASyncTasks,一个从httpPost检索一个值,另一个更新UI的一些元素(包括listview)。 问题是,由于两个ASyncTasks共享相同的后台线程,如果网络操作首先启动并且运行缓慢(由于网络连接不良)。其他背景线程花费了太多时间使应用程序不负责任。

由于两个ASyncTasks都是独立的,因此非常愚蠢地等待另一个。这将是更合乎逻辑的asynctasks不同的类使用不同的线程,我错了吗?

阅读ASyncTask文档。谈谈使用 executeOnExecutor(),但我怎样才能在低于11的API级别解决这个问题?

这是一个重现“问题”的小例子

        new Task1().execute();
        new Task2().execute();

使用

public class Task1 extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... params) {
        GLog.e("doInBackground start 1");
        SystemClock.sleep(9000);
        GLog.e("doInBackground end 1");
        return null;
    }

    @Override
    protected void onPreExecute() {
        GLog.e("onPreExecute 1");
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Void result) {
        GLog.e("onPostExecute 1");
        super.onPostExecute(result);
    }

}

public class Task2 extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        GLog.e("onPreExecute 2");
        super.onPreExecute();
    }

    @Override
    protected Void doInBackground(Void... params) {
        GLog.e("doInBackground start 2");
        SystemClock.sleep(9000);
        GLog.e("doInBackground end 2");
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        GLog.e("onPostExecute 2");
        super.onPostExecute(result);
    }

}

3 个答案:

答案 0 :(得分:49)

这就是我在代码中处理这个问题的方法:

if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
    new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
    new MyAsyncTask().execute();
}

分别用您的MyAsyncTaskTask1替换Task2。基本上AsyncTask中的更改出现在Honeycomb中(请参阅“执行顺序”部分中的Android SDK文档here),因此在此之前,您可以像往常一样启动它,对于HC和up,如果你这样做,请使用executeOnExecutor()不像新的行为(我认为没有人)

答案 1 :(得分:7)

稍微更通用的方法是将两个辅助方法放在实用程序类中,如下所示:

class Utils {

    @SuppressLint("NewApi")
    public static <P, T extends AsyncTask<P, ?, ?>> void execute(T task, P... params) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
        } else {
            task.execute(params);
        }
    }
}

然后,您可以使用Utils.execute(mytask)Utils.execute(mytask, params)执行任务,它将负责并行执行它们。

答案 2 :(得分:1)

问题是每个AsyncTask都运行在编码到API中的相同ThreadPoolExecutor中。此ThreadPoolExecutor可以根据您的Android版本创建不同数量的WorkerThread。我不记得数字版本,但想法是在较旧的Android版本中它是1 WorkerThread。然后在更高版本中将其更新为5。最近再次回到了1。这就是您的AsyncTasks被阻止的原因。它们在同一个WorkerThread上运行,因此它们按顺序执行。尝试使用带有THREAD_POOL_EXECUTOR的executeOnExecutor来实现真正的并行执行。但是,您只能在API 11之后使用它。