スポンサーリンク

JavaのThread, Runnable世代がasync/awaitに躓く理由

前提

もろに私がそうでした、ちょうどAndroid2の時代で開発にはJava1.4でした。
このころはThreadにてRunnableを使い、処理完了後をコールバックにてHandler.pos()してメインスレッドに戻していました。

無限にネストが続くasync/await地獄

最下層メソッドが非同期になったのでasyncメソッドにするとコールする上位メソッドすべてにasync修飾詞を付ける地獄にハマってしまう。
可読性の悪さに気が狂いそうになる・・・。

実際にはTOP部であるUIイベント部に

await Task.Run(() => 
  処理A();
  処理B();
);

の様にすれば良いだけです。

要点

Runnable世代はメインメソッドでRunnableを実行するとメインスレッドはそのまま次の処理に移行するという常識になっている気がしており実際に私がそうでした。

Runnableは並列処理の色が強くUIスレッドのロックを意識したものではないと思います。
なので実行するとスレッドIDも変わりサブスレッドで実行されます。

async/awaitは同期を取るという意味になると思いますので、そのメソッドの中は勝手にサブスレッドで動くわけではありません。(私は自動でサブスレッドで走ると思っていました・・・)

Runnableは先に非同期化しておいてその中で処理を実装し、コールバック後に同期を取ります。
async/awaitは先に同期化を定義しておき、そのメソッドの中で非同期処理を行う設計になるのでしょうね。

そう考えると先ほどのコード

await Task.Run(() =>   
  処理A();
  処理B();
);

はRunnable世代にはまだ理解しやすいのかなと思います。
コールバックが不要なのはうれしいですね。
苦手意識があったasync/awaitもこれで取っつきやすくなった気がします。