akkaの勉強をしていてFutureを使ったサンプルを書いていた時に
馴染みの!?というか一回スルーした記憶のあるエラーが発生!!
なにやらExecutionContextとがありませぬ、というような内容です
さて
またスルーしてもいいのですが、DRYの原則でレイジーなエンジニアを演じます。
ということで
ScalaのExecutionContextって何?きちんと理解して良いエンジニアになろう
Contents
きっかけはコンパイラにExecutionContextで怒られたこと
akka httpを勉強中にサンプルコードを作ってるにあったってFutureを使った時、以下のようなコンパイラーエラーがでた
Cannot find an implicit ExecutionContext. You might pass [error] an (implicit ec: ExecutionContext) parameter to your method [error] or import scala.concurrent.ExecutionContext.Implicits.global. [error] Future(HttpResponse(entity = "pong")) [error] ^ [error] one error found [error] (compile:compileIncremental) Compilation failed
さてここで安直に言われた通り
import scala.concurrent.ExecutionContext.Implicits.global
するだけでは、いつまでたっても理解が進みません。
今日は一手間っとって、このExecutionContext とやらを理解しておきましょう
ExecutionContextとはRunnableをうまいこと実行してくれる人です
私は関数やオブジェクトを調べる時は、まず
ソースコードの説明や本家サイトの説明から、理解しようとしています。今回はソースコードの説明によると以下の通りです
ExecutionContextは非同期でRunnableを実行してくれる人です。 一般的には実行はスレッドで行われますが、その限りではないことは知っておきましょう。 場合によって同期処理もさせることもできますが、明示的にスレッドセーフなRunnableを渡しましょうね。
それぞれのアプリケーションの要件によってかっこよく使い分けたい
ものですが、いきなりいろいろ覚えるのも大変なのでまずは、よく使うExecutionContext.globalを抑えましょう。
ExecutionContext.globalは
ExecutionContext.globalはExecutionContextの一つの実装例で、
ExecutionContext.globalといのはForkJoinPoolによって実装されています
スレッド数の上限があって、基本はスレッドでうまいことCPUを効率化してくれるのですが、ファイル読み込みなどのブロッキング処理があると、そのブロック処理に引っ張られてうまくスケジューリングしてくれない可能性があります。そういいう時はblocking句で明示的にExecutionContextに通知してあげることで、「あ、ブロッキング処理走るから、新たにスレッド立ててやろうか」と思ってくれるそうです。
この挙動はExecuteionContextを継承する実装によりけりでExecutionContext.globalについてはManagedBlockerを実装しているので、それでよきに計らってくれるとのことです。
ところで
Fork joinってなんでしたっけ?昔C言語やっていた時には触れたことあるよ〜な。
ということでこちらの記事に詳しく書かれていますが、要はfork()でスレッド立ててjoinで終了というモデルですね。
まとめ、中身を理解したなら(結局)global使ってもいいけど
このように
ExecutionContext.globalの特性として、
スレッド数の上限がある(初期設定はプロセス数)だとか、ブロッキング処理に弱いだとか特性を知っておく
のと知らないのでは問題発生時の切り分けや解決までの時間に雲泥の差が出ます。
ということで今回は
ScalaのExecutionContextって何?きちんと理解して良いエンジニアになろう
という記事でした。
参考参照
https://docs.scala-lang.org/overviews/core/futures.html#blocking-inside-a-future
セプテーニ・オリジナルのブログ: https://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html