LoginSignup
68

More than 5 years have passed since last update.

Android - AsyncTaskの直列処理?並列処理?

Last updated at Posted at 2014-12-05

今日の結論

  • AsyncTaskを直列で使うには・・・
    AsyncTask.execute()

  • AsyncTaskを並列で使うには・・・
    AsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)

経緯

作業中のアプリにて、動作確認を行っていたところ、なかなかAPIアクセス処理が完了しないという現象に見舞われました。デバックしてみると、
↓のようなAsyncTask.doInBackgroundがなかなか始まらないということがわかりました。

new AsyncTask() {
    @Override
    protected Object doInBackground(Object[] objects) {
        // APIアクセスの処理
        return null;
    }
}.execute();

参考

http://ayadadev.blogspot.jp/2013/08/asynctask.html
http://cocree.hateblo.jp/entry/2014/06/03/152107

AsyncTask.execute()は直列で実行されているらしい・・・。

直列実行してるって??こんな感じ??脳内イメージ↓

  1. メインThreadからAsyncTaskをインスタンス生成+execute()
  2. AsyncTaskHolderにAsyncTaskのインスタンスQueueにためる
  3. バックグラウンドThreadにアタッチしたら、溜まったQueueを順次実行していく

1.を何回もやったり、1.のタスクの中でひと際重い処理があったりすると、次回実行されるタスクの開始される時間がどんどん遅くなる・・・。結局、生成したAsyncTaskでどこか重い処理があると、すべてのQueueを実行し終えるのには、シコタマ時間がかかる・・・。

直列でやってみた

本当に直列実行・並列実行されてる?

public class AsyncTaskActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task);


        AsyncTask task1 = new AsyncTask() {

            @Override
            protected Object doInBackground(Object[] objects) {
                Log.v("task1", "start!!!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            protected void onPostExecute(Object o) {
                super.onPostExecute(o);
                Log.v("task1", "done!!!");
            }
        }
          .execute();
        //.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);


        AsyncTask task2 = new AsyncTask() {

            @Override
            protected Object doInBackground(Object[] objects) {
                Log.v("task2", "start!!!");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            protected void onPostExecute(Object o) {
                super.onPostExecute(o);
                Log.v("task2", "done!!!");
            }
        }
         .execute();
       //.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }
}

実行結果

12-05 09:09:53.665    task1﹕ start!!!
12-05 09:09:54.665    task1﹕ done!!!
12-05 09:09:54.665    task2﹕ start!!!
12-05 09:09:54.765    task2﹕ done!!!

おぉ!!!
task1の処理が完了するまで、task2が開始されていません。直列ですね。
Thread.sleepで設定した時間がぴったりでした(たまたま?)

並列でやってみた

.execute()
をコメントして、
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
のコメントアウト外してみました・・・・

実行結果

12-05 09:17:41.041    task1﹕ start!!!
12-05 09:17:41.045    task2﹕ start!!!
12-05 09:17:41.089    task2﹕ done!!!
12-05 09:17:42.045    task1﹕ done!!!

task1終了前に、task2が実行されています。
並列になってますね。

まとめ

  • AsyncTaskで「直列に実行する」か、「並列に実行する」かは、実行処理の書き方で選択できる。
  • AsyncTask多用していて、AsyncTaskが完了まで時間がかかるなぁと感じたら、実行処理を見直してみる。

最後に

今回の場合、AsyncTaskで実行したいAPIアクセス同士依存性(前に実行したAPIアクセス次第で、今回実施するAPIアクセスが変わるような関係性)がないので、並列で実行するよう修正しました。・・・ん〜アクセスに依存性がある場合は、直列で実行させようとか、そういうことではないので、使用する方は、その用途を改めて考え直して対応しましょう(なげやり)

以上です。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
68