- - PR -
Hashtable またはvectorの要素を生成/削除する時にeventの生成できるのでしょうか。
| 投稿者 | 投稿内容 |
|---|---|
|
投稿日時: 2002-05-01 19:37
しょむさんの言うとおり同期は大切ですね。
Vector, Hashtable は同期が考慮されているのですが、使う側でプリミティブでないアクセスをしている例を良く見かけます。 サブクラスの場合も慎重にやればそれ自体はそれ程難しくないのですが、リスナを 配列や Vector 等のコレクションに収めているときもう一つ注意が必要です。 例えば複数のリスナが登録されているとき、先に呼び出されたリスナがそのコールバック内で自分自身のリスナ登録を削除したり、新たなリスナを追加したりしたときに、未だ呼ばれていないリスナにちゃんと通知がされること、二重に呼び出したりしないことに留意しなければなりません。これを間違うと単一スレッドでも問題を起こしかねません。 |
|
投稿日時: 2002-05-02 10:46
> これを間違うと単一スレッドでも問題を起こしかねません。
同期だけでは不十分ということを言っていますか? listenersのcloneをしてから通知するような配慮が必要ということですかね。 |
|
投稿日時: 2002-05-02 17:42
まりりさん
貴重な情報とご意見本当にありがとうございます。 しょむさん コードまで組んで下さったのですね! 参考させていただきます。 イベントって真髄はコールバックですね。 すごく分かるような気がします。 ほんとうにありがとう御座いました。 Kissingerさんのご意見に私はすごく深刻に受け止めています。 こわ〜ーい〜! 本当に真剣に考えなければ使い物にならないかも知れません。 ただ、Hashtable とVectorはロックの仕組みを実装しているので アクセス能率悪いと言われてHashmapとArrayListのほうが推奨されるって いう記憶を持っています。 このロックの仕組みこそ同期のために用意されているのではないかと思いますが、、、 これでも安全ではないでしょうか。 |
|
投稿日時: 2002-05-02 17:56
KissingerさんWrote: <<<<<<<<<<<<<<<<<< 先に呼び出されたリスナがそのコールバック内で自分自身のリスナ登録を削除したり、新たなリスナを追加したりしたときに、未だ呼ばれていないリスナにちゃんと通知がされること、二重に呼び出したりしないことに留意しなければなりません。これを間違うと単一スレッドでも問題を起こしかねません。 >>>>>>>>>>>>>>>>>> 幾度も読んだ後、 おっしゃることは同期問題ではないような気がします、、、 簡単なコードでも用いてご解説いただければ幸いですが、 理解力不足の私にはやはり精確なイメージを涌いてこないです。 重大なテーマだけにもう一回フォローしていただけませんか。 |
|
投稿日時: 2002-05-02 20:24
> おっしゃることは同期問題ではないような気がします、
そうです。同期問題だけでないということです。 > 簡単なコードでも用いてご解説いただければ幸いですが、 少し回り道ですが、目的や用途を整理したほうが良いかも知れません。 (最初の私の発言では直接的な回答を提供しようとするあまり、不親切だたかも知れません。) ■分析 1.汎用クラスを作るのか、そとも特定用途でのオブジェクト追加削除を把握したいのか。 2.マルチスレッドで使う(またはそうなる可能性が高い)のか。 3.リスナへの通知の中からリスナ登録削除をする必要があるのか。 4.リスナは2つ以上になる可能性が高いのか。 ■考察 A.特定用途ならそのアプリケーションで何をやりたいのか注目したほうが良いでしょう。 まず「Hashtable に何かを追加削除したときに通知する。」と考えるよりも「会員名簿に新しい会員を登録する。」のように。そうすればリスナの登録先は Hasntableクラスではなく「会員名簿クラス」になるわけです。 そしてその会員登録時にどのオブジェクトにどのように作用したいかで、コールバックするか直接メソッドを呼び出しするか決まってくるでしょう。(多分issekiさんも検討済みと思われますが) B.マルチスレッドのときは処理中に他のスレッドに追い越されたときのことを考慮した方が良いです。 例えばコレクションにオブジェクトを追加した後、「さあリスナに通知しよう。」とした所で他のスレッドからそのオブジェクトが削除されたりしたら、リスナは混乱するかも知れません。 アプリケーションを作る立場なら何事も無かったかのようにアプリケーション側で対処する設計もできるのですが、ライブラリを作るならちゃんと面倒をみる方が良いでしょう。 これが【同期問題】です。 方法としては synchronized を使うとか、コマンドパターンを使ってリクエストをシリアル化するとかがあります。 C.リスナへの通知の中でリスナの登録削除を行わないなら、私が以前書いたような注意は必要ありません。その可能性があるなら miki さんの発言に1つの答えがあります。 これは1つの方法ですが、リスナの一覧を一度コピーし、そのコピーを元に通知を行うことです。コピー中に他のスレッドからアクセスされないように注意しましょう。(Vector や Hashtable が持っている toArray やコレクションによるコンストラクタを使用したほうが良いでしょう。) D.もしリスナ通知の中からが「他のリスナ」の登録削除を行わないという制約が付けられるならもっと良い方法があるかも知れません。 リスナの一覧(配列やVector)を後ろから処理すれば、コピーする手間が省けるでしょう。 ごめんなさい今は時間が無いので具体的なコード例は提示できません。 というよりは上記のように場合分けを整理しなければ必要以上に神経質な答えにになってしまうかもしれません。 |
|
投稿日時: 2002-05-03 13:14
Kissingerさん
こんにちは お世話になっております。 丁寧なご解説ありがとうございます。 初心者ではありますが それでもご解説はJAVAプログラミングに置いて一般性が高いと感じることができます。 本当にいい勉強になりました。 それに 1. clone 2. synchronized 3. toArray 4. collection 等の小道具を使いこなす重要性も認識させていただきました。 >ごめんなさい今は時間が無いので具体的なコード例は提示できません。 こちらこそ厚かましい要求をしました。 貴重なご時間を費やされて申し訳御座いません! (でも、、、これからもこんなレベルの高いレスを拝見したいな、、、) ーーーーーーーーーーーーーーーーーーーーーーー マルチスレッド+データの整合性問題=頭痛い種 ーーーーーーーーーーーーーーーーーーーーーーー |
