ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

手作りネットプロトコル工房コミュのSwing が スレッドセーフじゃないのは イモか。

  • mixiチェック
  • このエントリーをはてなブックマークに追加
Swingを使ってアプリを書いているとき、イベントハンドラから 他のSwingコンポーネントのメソッドを呼んだりしたときに、動作がおかしくなって、何故なのか原因がわからずに、よく悩む。 ドキュメントを読んでみると、「Swingは スレッドセーフじゃありません。」と書いてある。 あれこれ悩むうちに、イベントハンドラの中からSwingコンポーネントを操作する時は、必ず SwingUtil.invokeLater() を介することが必須である事を知る。 そんなことわかるわけが無い。 最初からそう書いておいて欲しい。 わかりづらいことこの上ない。

だけど、自分でマルチスレッドアプリを書いていて気がついた。 直接操作してはいけない、という事は、実は当たり前なのだ。



マルチスレッドでの処理ってセルフサービスの食堂の様なものだ。 セルフサービスの店に、客がかわるがわるやってきて、自分で食堂の処理を行う。 客が自ら コップを取って、水を汲んで、飲み食いして、使い終わったら下げ口に戻すというようにすることで、従業員の仕事を減らすわけだ。

ところが、これだと、たまに行儀の悪い客が来て、やるべきことをやらずにほったらかしにしてしまうヤツが居ないとは限らない。 そういう行儀の悪い客が、食べ過ぎてゲロを吐いて、そのまま帰ってしまうということも稀にある。 店の中には誰も片付けないままのゲロが残ることになる。

もちろん、セルフサービスのマニュアルの中に、「前の客が残したゲロを片付ける」という事を書いておくことも出来る。 だけど、どうしても、次の客が来るまでは、ゲロが残ってしまう。 しかも、次の客が来なければ、永遠にゲロは消えない。 客だって、食事の前にゲロを片付けるとあっては気が重い。

どうすればいいのだろうか。 それは切り盛りのオバちゃんを雇う事だ。 「おばちゃん、水ちょーだい!」「はいはい!」「おばちゃん、天丼!」「はいはい!」 「おばちゃん、ソバが来ないよ!」 「はいはい!」 ということだ。 こうすれば、何か不測の事態が起こっても、おばちゃんがちゃんと責任を持って片付けてくれる。

確かに、おばちゃんは忙しくなるが、おばちゃんに任せておけば絶対に間違いがない。

みんなでセルフサービスにしていると、順番が前後して処理がうまく行かないということがままある。 Aさんがコップを置いて、Bさんがそのコップに水を入れる、という風にしたいのに、Bさんが先に来てしまい、コップが無いので、帰ってしまう。 Aさんが後から来てコップを置いて帰ってしまう、ということがけっこうよくおこってしまうのだ。 そうすると、処理されなかったコップと、コップ無しで流された水がどんどん増えてしまう。

Aさんが、コップを見て 水を取って、さあ入れよう!と思ったら、いつのまにか、Bさんがコップを片付けてしまった、気づかず水をバシャっとやってしまう、なんていうことも起こる。 そういうことにならないように、入り口にゲートをつけて 必ずこのステージには、2人しか入らないようにする、というような事もするのだけど、店中ゲートだらけになってしまって、非常に疲れてしまう。

おばちゃんひとりならそういうことが無い。 「まぁ〜 あんたら客がヘダにてつだってくれるよりゃ、あだしひとりでしごとしたほが、はやーて!」 ということだ。 だから、どうしても 「おばちゃん」が必要になってくるのだ。 このおばちゃんのことを、プログラミング用語で メッセージキューと呼ぶ。

Swingは 自分でメッセージキューを実装している。 これはWin32アプリのメッセージループと似たような仕掛けになっていて、処理をする時は、メッセージをキューに『ポスト』するようになっている。 ポストっていうのは、この手のアプリの専門用語で、キューに処理を追加する事を 投稿になぞらえて ポストと呼ぶ慣例になっている。 僕が知る限り、これは win32プログラミングの用語でもあった。 win32には postMessage() という極めて有名なAPIがある。 Swingはキューを使っているのに、Delphiとか VBとかは メッセージキューを使ってないじゃないか、という気がするけども、Delphi/VB どちらも Win32をベースに作られているので、結局 暗黙の内にメッセージキューを使うことになる。

スレッドセーフというのは、基本的に極めて難しい要素を持っている。失敗するパターンは一通りでなく、失敗した場合の復帰のパターンもとても複雑だ。 だから、ロジックがある一定以上複雑になってくると、かならず「おばちゃん」が必要になる。

だから Swing で invokeLater を使わないといけないというのは、実は案外当然のことなのかもしれない。

プログラミングって奥が深い。

P.S. でも、本当はイベントハンドラを実行している間は 他の処理はブロックされていなければいけないはずだし、ブロックされていて何かまずいのであれば、 一般的に ProcessMessages というたまったメッセージを消化する関数があって、それを呼び出せば上手く動くのが通例だ。 ところが、このProcessMessagesが Swingには 用意されていない。 Win32プログラミングだと、イベントハンドラで処理を行い、適度の間隔を置いてProcessMessages を呼び出すのが定石なのだけど 、Swingはここに全く違う発想を持っている。 そもそも 直接操作せずに、自作のメッセージを介して処理をしろよ、ということなのだろう。

コメント(11)

友達より、JAVAの画面を作るのは難しいことを聞いて、なぜかよくわからなかったのですが、
そういう理由でしたか。

β版のころ(何年前やねん)のころにJava.awtで遊んでいた頃は
難しさがよくわからなかったのですが。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

手作りネットプロトコル工房 更新情報

手作りネットプロトコル工房のメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング