今週は第56回を開催しました!
引き続きKotlin Hands-onをすすめています。
前回の様子はコチラ↓
[第56回の様子]
2021/3/17に第56回を開催した。
参加メンバーは自分をいれて3名。メンバーは最近固定気味。
今回は久しぶりにドライバ役を担当した!
勉強会本編の内容としては、ひき続きIntroduction to Coroutines and Channelsハンズオンを進めた。第5章 Concurrencyがようやく最後まで終わった!
しかし終わりがめちゃくちゃ気になる感じだった……。早く次の章を読みたい!
[学んだことや疑問点]
- Introduction to Coroutines and Channels: 5. Concurrency
- 第5章のラストのパート、
Dispatchersに関する説明のところ。 - async関数の引数として以下のように
Dispatchers.DEFAULTを指定すると、スレッドプールからもってきたスレッドで処理が実行されるようになる
async(Dispatchers.Default) {
log("starting loading for ${repo.name}")
service.getRepoContributors(req.org, repo.name)
.also { logUsers(repo, it) }
.bodyList()
}
- メインスレッドで処理を実行したい場合には、以下のように
Dispatchers.Mainを指定すればよい。今回の場合SwingのUIメインスレッドで結果を更新する処理を実行して画面に反映する必要があるのでこうなる。 - ただし、UIメインスレッドが他の処理で忙しい場合は、その処理が終わるまで以下の処理は実行されないことになる
launch(Dispatchers.Main) {
updateResults()
}
Dispatchersを呼び出される関数側が明示的に指定するのはあまり良いお作法ではない- むしろ、外部のスコープの
Dispatchersをそのまま利用するのがベストプラクティスとされているらしい - 以下のようにデフォルトを指定してsuspend関数を起動し、メインスレッドに戻ってくる、というような形。
- テスト用には
TestCoroutineDispatcherというディスパッチャがいるらしい。詳細は第9章を待て。
launch(Dispatchers.Default) {
val users = loadContributorsConcurrent(service, req) // これがsuspend関数
withContext(Dispatchers.Main) {
updateResults(users, startTime)
}
}
- 上記を別の方法で書くと、
launch(Dispatchers.Default) { ... } .join()とJavaのマルチスレッドっぽい書き方になる、のは5章のはじめに見た通り。 join()が冗長な書き方と書かれていたけれど、withContext(Dispatchers.Main)の方がタイプ数多そうなんですがそれは……- それはともかくとして、
Dispatchersはスレッド(スレッドプール)とメモリ上に溜まっているcoroutineのジョブをうまく取り持ってさばいてくれるオブジェクト、という理解でよさそう。賢いオブジェクトだなあ。 - ここまで読んで、コルーチンのスコープとかわずかに触れられていて先週から気になっていた部分の説明が結局少なかったことに気づいた。
- 最後の文章を読むと以下のように、「次週、乞うご期待」とでも言わんばかりに疑問文が並べられていた……これは次の章が楽しみ!
- 外部スコープのディスパッチャーを使うってそもそもどうなってるの?
- より正確には外部スコープのコンテキストからディスパッチャーを使う?
- コルーチンのスコープとコンテキストって違うの?
- コルーチンスコープの呼び出しのなかで新しくasyncのコルーチンを開始しなければならないのはなぜ?などなど
[まとめ]
モブプログラミング・スタイルで、Introduction to Coroutines and Channelsハンズオンを進めた。
コルーチンに関わるDispatchersの概念が少しだけ理解できた気がする!こいつがきっと上手いこと処理してくれてるんだろうなあ。
そして先週から続く謎のコルーチンスコープ。コンテキストなる用語も出てきて、さらに次週が楽しみです……!
今週のプルリクエストはこちら。