以下のコードにおいて。
% java ThreadWaitTest 2
の場合はaと表示したまま止まりますが、
% java ThreadWaitTest 1
の場合はスレッドの終了に伴ってwait()が切れ、bまで表示します。
私の望む動作は前者です。
後者の場合、これはつまりスレッドをwaitした際の待機プールがスレッドオブジェクトの場合、そのスレッドの実行が終了すると待機プールにある待機スレッドを自動でnotify()してしまうことを意味していると思うのですが、この解釈はあっていますか?
Java のAPIドキュメントに
「別のスレッドが notify メソッドまたは notifyAll メソッドを呼び出してこのオブジェクトのモニター上で待機するスレッドに通知を出すまで待機します」
とあるように、ユーザが明確的にnotifyしないと起こらないと思いこんでいました。
なぜこういう仕様になっているのでしょうか?
また、この仕様について詳しく書いてあるサイトやドキュメントなどありませんでしょうか?
public class ThreadWaitTest extends Thread {
public Object mutex = new Object();
public static void main(String[] args) {
try {
ThreadWaitTest test = new ThreadWaitTest();
test.start();
System.out.println("a");
switch (new Integer(args[0])) {
case 1:
synchronized(test) {
test.wait();
}
break;
case 2:
synchronized(test.mutex) {
test.mutex.wait();
}
break;
}
System.out.println("b");
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException ie){
ie.printStackTrace();}
}
}
No.2ベストアンサー
- 回答日時:
自信なし。
---
"spruious wakeup"みたいですが・・・。
("spurious wakeup"については、
「1.5以降のjavadocのObject#wait(long)の項」、
または
「Effective Java 項50」
などに簡単に記されている)
(今のところ)仕様とはされてないが、
現実には認知されている現象、というところだと思います。
---
"spurious wakeup"については、よく知らないので、
ネットで検索したり、
sunの「Bug Database」などで検索してみてください。
http://bugs.sun.com/bugdatabase/view_bug.do?bug_ …
ご回答ありがとうございます。
wait()しか使っていなかったので、wait(long)の方に目を通していませんでした。
私が遭遇した「スレッドの終了時、そのスレッドオブジェクトの待機プールにある待機スレッドがnotify()される」という現象は spruious wakeup の一例に過ぎないのですかね。
ドキュメントに 稀に生じる と書いてあるところも怖いところです。
No.1
- 回答日時:
JDKにはそれらしい記述がありませんでしたね。
推測ですが、Threadが一度start()し、その後停止状態に遷移した場合、そのスレッドは二度とstart()できません。
もしnotify()を呼ぶ役目がそのThreadに課せられていたとしたら、二度とwait()状態から戻れない可能性もあるわけです。
ですので、「無効なオブジェクト」と化したThreadクラスは、その直前にnotifyAll()でもしているんじゃないでしょうか?
ご回答ありがとうございます。
>「無効なオブジェクト」と化したThreadクラスは、その直前にnotifyAll()でもしているんじゃないでしょうか?
うむむ、なるほど。
しかしこの現象をみつけるまで、プログラムのバグを特定できずえらい時間がかかってしまいました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java java final 1 2022/06/10 22:49
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- Ruby 【JAVA】数字をひし形に出力するプログラムについて 2 2022/07/11 23:32
- C言語・C++・C# C# DatagridviewにExcelシートを反映するとエラーが出る 2 2023/05/06 17:12
- C言語・C++・C# Windows Formアプリからコンソールを呼び出して文字を出力させたい 8 2023/05/09 10:53
- Java Java プログラム public class Main { public static void 3 2023/08/10 23:46
- Java java 飾子を付けること(public static・・・) ・コンソールへの出力処理はmainメ 2 2022/06/16 19:34
- JavaScript [Java] Edgeでのアドレスバー非表示について 3 2022/04/20 17:51
- Excel(エクセル) 【エクセルマクロ】既に開いているIEの、サイズや表示位置を変更するには 4 2022/12/01 22:57
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
JAVA ID重複処理
-
再度、スレッドが実行中かどう...
-
無限ループをわざと作って時計...
-
ExcelVBA で文字列の特定の文字...
-
ブラウザを閉じた後のサーバ側...
-
バッチって何でしょうか?
-
ラベルの表示までが異常に遅い...
-
画面系イベントの優先度を上げたい
-
Ajaxの実行速度と読み方について
-
C#でバックグラウンド処理から...
-
doGetとdoPostの違い
-
java(swing)で、登録ボタンを押...
-
JavaScriptからJAVAクラスを呼...
-
スレッド1とスレッド2を交互に...
-
C#の処理をリアルタイムに表示...
-
Javaプログラムからポップアッ...
-
素数判定を再帰処理で
-
tryの終了
-
ラジオボタンの選択判定
-
Javaでのデバッグコード削除
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
tryの終了
-
数値の定数を付ける時
-
Javaでのデバッグコード削除
-
C#で別スレッドの終了を知りたい
-
[Java] while(true)の意味
-
Javaプログラムからポップアッ...
-
Tomcatのスレッドを破棄する方法
-
ラジオボタンの選択判定
-
JavaScriptからJAVAクラスを呼...
-
素数判定を再帰処理で
-
PHPでDB処理中にプログレスバー...
-
Javaアプリケーション実行の返...
-
WPF C#でF10のイベント取得方法...
-
doGetとdoPostの違い
-
switch文の中に、throws new Ex...
-
Tomcat高負荷時の設定について
-
ラベルの表示までが異常に遅い...
-
ExcelVBA で文字列の特定の文字...
-
JDBCでテーブルUPDATE後の再検...
-
SwingUtilities.invokeLater(ne...
おすすめ情報