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

## 今日の結論
 
- AsyncTaskを直列で使うには・・・
`AsyncTask.execute()`

- AsyncTaskを並列で使うには・・・
`AsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)` 
 
## 経緯
 
作業中のアプリにて、動作確認を行っていたところ、なかなかAPIアクセス処理が完了しないという現象に見舞われました。デバックしてみると、
↓のようなAsyncTask.doInBackgroundがなかなか始まらないということがわかりました。

```python
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()
1. AsyncTaskHolderにAsyncTaskのインスタンスQueueにためる
1. バックグラウンドThreadにアタッチしたら、溜まったQueueを順次実行していく
 
1.を何回もやったり、1.のタスクの中でひと際重い処理があったりすると、次回実行されるタスクの開始される時間がどんどん遅くなる・・・。結局、生成したAsyncTaskでどこか重い処理があると、すべてのQueueを実行し終えるのには、シコタマ時間がかかる・・・。
 
 
 
## 直列でやってみた 
本当に直列実行・並列実行されてる？

```python
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アクセスが変わるような関係性）がないので、並列で実行するよう修正しました。・・・ん〜アクセスに依存性がある場合は、直列で実行させようとか、そういうことではないので、使用する方は、その用途を改めて考え直して対応しましょう（なげやり）
 



以上です。