« ConvolutionFilterで遊ぶ その4 | メイン | 最適化してます? »

絵で見るThread

Flasher各方面で話題のorg.libspark.thread.Threadだけど、最近ようやく使ってみた。
評判がいいのもうなづける素晴らしいライブラリだと思う。
もっと早く使ってみればよかった。。

ドキュメントがとてもよく出来ているので、使い方についてほとんど付け加えることはないんだけど、文章とコードだけだと、処理の実行単位とか実行順がわかりにくいかもしれないと思い(自分がそうだった)シーケンス図でまとめてみた。

ここまちがってるんじゃないの?みたいなつっこみ、絶賛募集してます。


シーケンス図の見方、超投げやりな説明




シーケンス図は、プログラムの実行時におけるインスタンスの処理の流れや、インスタンス間のコラボレーションの様子を表現できる。
インスタンスとインスタンスの寿命はこのように表現する。






時間は上から下へ流れる。
この図では、
1・ENTER_FRAMEイベントが起きた
2・誰かがnew A()を呼び出した
3・インスタンスAが生成された
事を表している。


Threadの実行単位は「実行関数」



Threadの実行単位は「実行関数」。
1フレーム※1に一度、Threadが持っている実行関数が1つだけ実行される。
2つは実行されない。※2
これ大事。
※1(1フレームと書いたが、フレームベースではなくintervalベースにすることもできるみたい)
※2(例外あり。event()参照)

runとfinalizeはデフォルトで用意されている実行関数。
runは必ず最初に呼び出される実行関数。
finalizeはThreadが終了する前に必ず呼び出される実行関数。






実行関数の中でnext()を呼ぶと、次の実行関数を予約できる。
予約された実行関数は、1フレーム1実行関数の原則に従い、次のフレームで実行される






実行関数の中でevent()を呼ぶと、任意のイベントが発生するまで待機状態になる。
イベントが発生すると予約した実行関数を実行する。
その後特に実行関数がなければ、finalize()が実行される
※(1フレーム1実行関数が基本だが、この場合は例外的に2つの実行関数(fとfinalize)が1フレームで実行される)






実行関数内でsleep()を呼ぶと、指定された時間のあいだ待機状態になる。
時間が過ぎると次の実行関数が実行される。


実行関数の定義まとめ


Threadの実行単位は実行関数なので、なにが実行関数なのかを意識した方が良い。
実行関数は、

  • run()

  • next()に渡された関数

  • event()に渡された関数

  • finalize()


上記に含まれないThread内の関数は実行関数ではないので注意。


Threadの親子関係



実行関数の中で新しいThreadを生成すると、Threadの親子関係が出来る。
AはBの親、BはCの親。
親子関係のあるスレッドは、それぞれ独立した時間軸を持ち実行関数を実行していく






子Threadの実行関数は必ず親Threadの実行関数より先に実行される。




Thread.graffle-19.jpg

子Threadがjoin()された時は、親Threadは子Threadのすべての実行関数が終了するまで次の実行関数の実行を待機する(待機状態になる)。
つまり、各Threadの独立した時間軸の一本化


Monitor



実行関数内で、Monitor::wait()を呼び出すと、そのThreadはMonitor::notify()が呼び出されるまで待機状態になる。
nonify()が呼び出された場合は即座に待機状態が解除され、notify()された同じフレームで実行関数が実行される。


待機状態まとめ


待機状態は、「時間指定あり待機状態」と「時間指定なし待機状態」に分けられる。

時間指定ありなし
・join(timeout time)したとき
・sleep()したとき
・join()したとき(引数なし)
・event()したとき
・Monitor.wait()したとき


割り込み



interrupt()を呼び出すと、割り込みフラグが立つ。
割り込み処理はこのフラグを使って実装する。
ちなみにinterrupt()は実行関数ではないので注意。






待機状態のときに割り込まれると、指定した割り込みハンドラが実行される。
割り込みハンドラは、Thread.interrupted ( )をつかって各実行関数ごとに記述する。
待機状態で割り込まれ、割り込みハンドラがない場合はエラーとなる。





たとえ親子関係にあっても、割り込みは子Threadに伝播しない
もし伝播させたい場合はorg.libspark.thread.utils.ParallelExecutorまたはorg.libspark.thread.utils.SerialExecutorを使用する。


トラックバック

このエントリーのトラックバックURL:
http://www.imajuk.com/mt4/mt-tb.cgi/44

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

About

2009年3月23日 23:19に投稿されたエントリーのページです。

ひとつ前の投稿は「ConvolutionFilterで遊ぶ その4」です。

次の投稿は「最適化してます?」です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。