今日の結論
-
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()は直列で実行されているらしい・・・。
直列実行してるって??こんな感じ??脳内イメージ↓
- メインThreadからAsyncTaskをインスタンス生成+execute()
- AsyncTaskHolderにAsyncTaskのインスタンスQueueにためる
- バックグラウンド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アクセスが変わるような関係性)がないので、並列で実行するよう修正しました。・・・ん〜アクセスに依存性がある場合は、直列で実行させようとか、そういうことではないので、使用する方は、その用途を改めて考え直して対応しましょう(なげやり)
以上です。