Javaでコルーチン実装書いてみた
当初、一つのグローバルオブジェクトを持ち回ってnotify()/wait()すればそのままコルーチンの実装に使えるんじゃないかなーと思って書き始めてみたけど、結局デッドロックになってしまって、結局スレッド数分のCondition*1を用意したらうまくいったので、その後はずっとかっこいいAPIになるようゴリゴリ修正してたら日曜がほぼ終わっていた。良い土日の潰し方だった。
イメージとしては、複数コースのあるトラックで各選手が待機してて、最初の選手が一周して隣のトラックの選手にバトンタッチ(Context#yield())して、次々と回っていくイメージ。
コルーチンなので走っている選手は1人だけ。
追記 2015/03/24 0:52:BlockingQueue使うようにした
@tyru いまの実装だと、普通にSingleThreadExecutorとか、Futureとか、BlockingQueue使ったほうが良いのでは?
— MURAOKA Taro (@kaoriya) 2015, 3月 22
@kaoriyaさんにアドバイスもらったので、BlockingQueueで書き直した。
BlockingQueueの中でも特にSynchronousBlockingQueueはGoのchannelと同じように使えて便利。パフォーマンスは知らない。
気になった所
https://twitter.com/tyru/status/579603710592040960
ただ気になるのがコルーチンって言語/ライブラリによってはyieldで値返せたりするけど、それは「コルーチン」の必須仕様に入ってたりするのかな。
正直
今までSpurious wakeup(見せかけの起動)を知らなかったのでもう直しようがない過去のお仕事のコードとかの罪滅ぼしというモチベーションもあったりした。
というか、Java並行処理本、つまみ食いじゃなくて通しで最後まで読むべきですね…
むしろ全部読まずに並行処理に足突っ込んじゃダメなことを痛感しました…
参考リンク
とても参考になった記事。
*1:1つのロックに対し複数の同期オブジェクトを使えるもの(アバウトな説明)