wait()とsleep()の違い
-
10-07-2019 - |
質問
スレッドの wait()
と sleep()
の違いは何ですか?
wait()
-ingスレッドはまだ実行モードにあり、CPUサイクルを使用しますが、 sleep()
-ingはCPUサイクルを消費しません。正しいですか?
両方 wait()
と sleep()
があるのはなぜですか:それらの実装は下位レベルでどのように変化しますか?
解決
A wait
は、「ウェイクアップ」できます。 notify
は待機中のモニター上で、 sleep
はできません。また、 sleep
ではなく、モニターオブジェクトの synchronized
ブロックで wait
(および notify
)が発生する必要があります。
Object mon = ...;
synchronized (mon) {
mon.wait();
}
この時点で、現在実行中のスレッドは待機し、モニターを解放します。別のスレッドが行う可能性があります
synchronized (mon) { mon.notify(); }
(同じ mon
オブジェクト上)と最初のスレッド(モニターで待機している唯一のスレッドであると想定)が起動します。
notifyAll
モニターで複数のスレッドが待機している場合–これにより、それらすべてが起動します。ただし、モニターの1つだけがモニターを取得でき( wait
は synchronized
ブロックにあることを忘れないでください)、–を続行できます。他のユーザーは、モニターのロックを取得できるまでブロックされます。
別のポイントは、 Object
自体(つまり、オブジェクトのモニターで待機する)に対して、 Thread
。
さらに別のポイントは、 wait
から偽のウェイクアップを取得できることです(つまり、待機中のスレッドは明確な理由なしに再開します)。次のように、ある条件で回転している間は、常に待機
する必要があります:
synchronized {
while (!condition) { mon.wait(); }
}
他のヒント
まだ言及されていない重要な違いの1つは、スレッドをスリープしている間、保持しているロックを 解除せず、待機中に wait()
であるオブジェクトのロックを解除することです呼び出されます。
synchronized(LOCK) {
Thread.sleep(1000); // LOCK is held
}
synchronized(LOCK) {
LOCK.wait(); // LOCK is not held
}
この投稿を見つけました役に立ちました。 Thread.sleep()
、 Thread.yield()
、および Object.wait()
の違いを人間の言葉で表します。引用するには:
最終的にはすべてOS’のスケジューラーに行き着きます。 タイムスライスをプロセスとスレッドに渡します。
sleep(n)
は、 “私はタイムスライスを終了しました。 もう1つは、少なくともnミリ秒です。” OSは、 要求された時間が経過するまでスリープスレッドをスケジュールします。
yield()
は、 “タイムスライスは完了しましたが、まだ作業が残っています do。” OSはスレッドにすぐに別のタイムスライスを与えることができ、 または、他のスレッドを与えるか、CPUを処理するスレッドを処理する justめました。
wait()
は、 “私はタイムスライスを終了しました。もう教えてはいけない 誰かがnotify()を呼び出すまでのタイムスライス。”sleep()
と同様に、OSは勝ちません’ t 誰かがnotify()
(または 他のいくつかのウェイクアップシナリオが発生します)。スレッドは、実行時にタイムスライスの残りも失います IOをブロックし、他のいくつかの状況下で。スレッドが機能する場合 タイムスライス全体を通して、OSはおよそ次のように強制的に制御します。
yield()
が呼び出された場合、他のプロセスを実行できます。
yield()
が必要になることはほとんどありませんが、 論理的なタスクの境界、yield()
might システムの改善を挿入 応答性(時間を犠牲にして—コンテキストスイッチは、 OSに戻って、無料ではありません)。目標に対する測定とテスト いつものように気をつけて。
ここには多くの答えがありますが、いずれにも言及されているセマンティックの区別は見つかりませんでした。
スレッド自体に関するものではありません。非常に異なるユースケースをサポートするため、両方の方法が必要です。
sleep()
は、スレッドを以前のようにスリープ状態に送信します。コンテキストをパックし、事前定義された時間だけ実行を停止します。そのため、期限までに起動するには、スレッド参照を知る必要があります。これは、マルチスレッド環境では一般的な状況ではありません。ほとんどの場合、時間同期(たとえば、正確に3.5秒で起動)やハードコーディングされた公平性(しばらくの間スリープし、他のスレッドが機能するようにする)に使用されます。
wait()
は、スレッド(またはメッセージ)同期メカニズムであり、参照が保存されていない(気にしない)スレッドに通知することができます。パブリッシュ/サブスクライブパターン( wait
== subscribeおよび notify()
== publish)と考えることができます。基本的にnotify()を使用すると、メッセージを送信します(まったく受信されない場合があり、通常は気にしません)。
要約すると、通常、時間同期には sleep()
を使用し、マルチスレッド同期には wait()
を使用します。
これらは、基盤となるOSに同じ方法で実装することも、まったく実装しないこともできます(以前のバージョンのJavaには実際のマルチスレッドがなかったため、おそらくいくつかの小さなVMもそうしません)。 JavaがVM上で実行されることを忘れないでください。コードは、実行されるVM / OS / HWに応じて異なるものに変換されます。
ここで、 wait()
メソッドと sleep()
メソッドの重要な違いをいくつかリストしました。
PS: また、リンクをクリックしてライブラリコードを表示します(内部作業。理解を深めるために少し遊んでください)。
wait()
-
wait()
メソッドはロックを解除します。 -
wait()
は、Object
クラスのメソッドです。 -
wait()
は非静的メソッドです-public final void wait()throws InterruptedException {// ...}
-
wait()
は、notify()
またはnotifyAll()
メソッドによって通知される必要があります。
誤ったアラームに対処するには、ループから -
wait()
メソッドを呼び出す必要があります。 -
wait()
メソッドは、同期コンテキスト(つまり、同期メソッドまたはブロック)から呼び出す必要があります。そうしないと、IllegalMonitorStateException
sleep()
-
sleep()
メソッドはロックを解除しません。 -
sleep()
は、java.lang.Thread
クラスのメソッドです。 -
sleep()
は静的メソッドです-public static void sleep(long millis、int nanos)throws InterruptedException {// ...}
- 指定された時間が経過すると、
sleep()
は完了します。 -
sleep()
ループから呼び出さない方がよい(つまり、以下のコードを参照)。 -
sleep()
はどこからでも呼び出すことができます。特定の要件はありません。
参照:待機とスリープの違い
waitメソッドとsleepメソッドを呼び出すためのコードスニペット
synchronized(monitor){
while(condition == true){
monitor.wait() //releases monitor lock
}
Thread.sleep(100); //puts current thread on Sleep
}
waitとsleepで作業した後に結論を出す重要な注意事項がいくつかあります。まず、wait()とsleep()を使用してサンプルを見てみましょう。
例1 : wait ()および sleep ()を使用:
synchronized(HandObject) {
while(isHandFree() == false) {
/* Hand is still busy on happy coding or something else, please wait */
HandObject.wait();
}
}
/* Get lock ^^, It is my turn, take a cup beer now */
while (beerIsAvailable() == false) {
/* Beer is still coming, not available, Hand still hold glass to get beer,
don't release hand to perform other task */
Thread.sleep(5000);
}
/* Enjoy my beer now ^^ */
drinkBeers();
/* I have drink enough, now hand can continue with other task: continue coding */
setHandFreeState(true);
synchronized(HandObject) {
HandObject.notifyAll();
}
重要な注意事項を明確にする:
- コールオン:
- wait():HandObjectオブジェクトを保持している現在のスレッドを呼び出します
- sleep():スレッド実行タスクget beerの呼び出し(クラスメソッドであるため、現在実行中のスレッドに影響します)
- 同期:
- wait():同期マルチスレッドが同じオブジェクトにアクセスするとき(HandObject)(複数のスレッド間の通信が必要なとき(スレッド実行コーディング、スレッド実行get beer)同じオブジェクトHandObjectへのアクセス)
- sleep():実行を継続するための待機状態のとき(待機中のビールが利用可能)
- ロックを保持:
- wait():他のオブジェクトのロックを解除し、実行する機会を与えます(HandObjectは無料で、他のジョブを実行できます)
- sleep():少なくともt回(または割り込みが発生するまで)ロックを保持します(ジョブはまだ終了せず、ロックを保持し続け、継続するために何らかの条件を待機しています)
- ウェイクアップ条件:
- wait():オブジェクトからnotify()、notifyAll()を呼び出すまで
- sleep():少なくとも時間が経過するか、割り込みを呼び出すまで
- 最後のポイントは、 estani が示すように、次の場合に使用です:
通常、時間同期にはsleep()を使用し、 マルチスレッド同期。
間違っている場合は修正してください。
wait()とsleep()の違い
-
基本的な違いは、
wait()
はObject
からのものであり、sleep()
はの静的メソッドですスレッド
。 -
大きな違いは、
wait()
はロックを解除し、sleep()
は待機中にロックを解除しないことです。
通常、 -
wait()
はスレッド間通信に使用され、sleep()
は実行時に一時停止を導入するために使用されます。一般的に -
wait()
は、同期内部から呼び出す必要があります。そうしないと、sleep()
を呼び出すことができますが、IllegalMonitorStateException
が発生します。どこでも。 -
wait()
からスレッドを再度開始するには、notify()
またはnotifyAll()
を呼び出す必要があります。sleep()に関しては、
指定された時間間隔後にスレッドが開始されます。
類似性
- 両方とも、現在のスレッドを実行不能状態にします。
- どちらもネイティブメソッドです。
これは非常に単純な質問です。これらの方法はどちらもまったく異なる用途があるためです。
主な違いは、待機中にスリープがロックまたはモニターを解放しない間、ロックまたはモニターの解放を待つことです。待機はスレッド間の通信に使用され、スリープは実行時に一時停止を導入するために使用されます。
これは明確で基本的な説明であり、それ以上必要な場合は読み続けてください。
wait()
メソッドの場合、スレッドは待機状態になり、 notify()
メソッド(または複数のスレッドが待機状態にあり、それらすべてのスレッドをウェイクアップする場合は、notifyAll()
)。また、 wait()
または notify()
または notifyAll()
メソッドにアクセスするには、同期またはオブジェクトロックまたはクラスロックが必要です。そしてもう1つ、スレッドが待機状態になると、そのスレッドをウェイクアップするために別のスレッドが必要になるため、 wait()
メソッドがスレッド間通信に使用されます。
ただし、 sleep()
の場合、これはプロセスを数秒間または希望する時間だけ保持するために使用されるメソッドです。そのスレッドを取り戻すために notify()
や notifyAll()
メソッドを呼び出す必要はないからです。または、そのスレッドをコールバックするために他のスレッドは必要ありません。ユーザーのターン後のゲームのように、数秒後に何かが起こるようにしたい場合、コンピューターが再生されるまでユーザーに待機させたい場合は、 sleep()
メソッドを指定できます。
そしてインタビューでよく聞かれるもう1つの重要な違い: sleep()
は Thread
クラスに属し、 wait()
は< code> Object クラス。
これらは、 sleep()
と wait()
のすべての違いです。
また、両方のメソッドには類似点があります。どちらもチェックされたステートメントなので、これらのメソッドにアクセスするにはcatchまたはthrowを試す必要があります。
これがお役に立てば幸いです。
source: http://www.jguru.com/faq/view。 jsp?EID = 47127
スレッド.sleep()
は現在のスレッドを&quot; Not Runnable&quot; 状態に送信します しばらくの間。スレッドは、取得したモニターを保持します -つまり、スレッドが現在同期ブロックまたはメソッドにある場合、他のスレッドはこのブロックまたはメソッドに入ることができません。別のスレッドがを呼び出す場合t.interrupt()
は、スリープ中のスレッドを起動します。sleepは静的メソッドであることに注意してください。つまり、sleepは常に 現在のスレッド(sleepメソッドを実行しているスレッド)。 A よくある間違いは、
t.sleep()
を呼び出すことです。tは異なるスレッドです。 それでも、スリープするのは現在のスレッドであり、tスレッドではありません。
t .suspend()
は非推奨です。それを使用すると、他のスレッドを停止することが可能です 現在のスレッドよりも。中断されたスレッドはすべてのモニターを保持し、 この状態は中断できないため、デッドロックが発生しやすくなります。
オブジェクト.wait()
は、現在のスレッドを&quot; Not Runnable&quot; 状態に送信し、sleep()
に似ていますが、ひねりがあります。待機はオブジェクトではなく、 糸;このオブジェクトを「ロックオブジェクト」と呼びます。lock.wait()
の前 呼び出されると、現在のスレッドはロックオブジェクトで同期する必要があります。wait()
次に、このロックを解除し、スレッドを「待機リスト」に追加します。 ロックに関連付けられています。後で、別のスレッドが 同じロックオブジェクトを呼び出し、lock.notify()
を呼び出します。これによりオリジナルが目覚め、 待機スレッド。基本的に、wait()
/notify()
は次のようなものですsleep()
/interrupt()
、アクティブなスレッドのみが直接を必要としません スリープ状態のスレッドへのポインタ。ただし、共有ロックオブジェクトのみ。
待機と睡眠は2つの異なるものです:
-
sleep()
では、スレッドは指定された期間動作を停止します。 -
wait()
では、通常、他のスレッドによって、待機中のオブジェクトに通知されるまでスレッドは動作を停止します。
sleep
は Thread
のメソッドであり、 wait
は Object
のメソッドであるため、 wait / notify
は、Javaで共有データを同期する技術です( monitor )、ただし sleep
は、それ自体を一時停止するスレッドの単純なメソッドです。
sleep()は、プロセスを数秒間または希望する時間だけ保持するために使用されるメソッドですが、wait()メソッドの場合、スレッドは待機状態になり、来ませんnotify()またはnotifyAll()を呼び出すまで自動的に戻ります。
主な違いは、 wait()がロックまたはモニターを解放するのに対し、sleep()は待機中にロックまたはモニターを解放しないことです。一般に、スレッド間の通信には待機が使用され、実行中に一時停止を導入するためにスリープが使用されます。
Thread.sleep()は、現在のスレッドを一定時間「実行不可」状態に移行します。スレッドは取得したモニターを保持します。つまり、スレッドが現在同期ブロックまたはメソッドにある場合、他のスレッドはこのブロックまたはメソッドに入ることができません。別のスレッドがt.interrupt()を呼び出すと、スリープ中のスレッドが起動します。スリープは静的メソッドであり、常に現在のスレッド(スリープメソッドを実行しているスレッド)に影響することに注意してください。よくある間違いは、tが異なるスレッドであるt.sleep()を呼び出すことです。それでも、スリープするのは現在のスレッドであり、tスレッドではありません。
object.wait()は、現在のスレッドを、sleep()のように「ひねりを加えた」「実行不能」状態にします。待機は、スレッドではなくオブジェクトで呼び出されます。このオブジェクトを「ロックオブジェクト」と呼びます。lock.wait()が呼び出される前に、現在のスレッドはロックオブジェクトで同期する必要があります。 wait()はこのロックを解除し、ロックに関連付けられた「待機リスト」にスレッドを追加します。後で、別のスレッドが同じロックオブジェクトで同期し、lock.notify()を呼び出すことができます。これにより、元の待機中のスレッドが起動します。基本的に、wait()/ notify()はsleep()/ interrupt()に似ており、アクティブスレッドのみがスリープスレッドへの直接ポインターを必要とせず、共有ロックオブジェクトのみを必要とします。
synchronized(LOCK) {
Thread.sleep(1000); // LOCK is held
}
synchronized(LOCK) {
LOCK.wait(); // LOCK is not held
}
上記のすべてのポイントを分類しましょう:
コールオン:
- wait():オブジェクトを呼び出します。現在のスレッドはロックオブジェクトで同期する必要があります。
- sleep():スレッドの呼び出し。常に現在実行中のスレッド。
同期済み:
- wait():同期された複数のスレッドが同じオブジェクトに1つずつアクセスする場合。
- sleep():同期された複数のスレッドが、スリープ中のスレッドのスリープを待機する場合。
ホールドロック:
- wait():他のオブジェクトが実行できるようにロックを解除します。
- sleep():タイムアウトが指定されているか、誰かが割り込んだ場合、少なくともt回ロックを保持します。
ウェイクアップ条件:
- wait():オブジェクトからnotify()、notifyAll()を呼び出すまで
- sleep():少なくとも時間が経過するか、interrupt()を呼び出します。
使用法:
- sleep():時間同期および;
- wait():マルチスレッド同期の場合。
Ref: diff sleep
および wait
wait
メソッドと sleep
メソッドは大きく異なります:
考えてみると、名前はその点で混乱しています。ただし、 sleep
は標準名であり、 wait
は WaitForSingleObject
または Win APIのWaitForMultipleObjects
。
簡単な言葉で言うと、sleepは「次のステートメントを実行しない」が他のスレッドから呼び出されるまでwaitです。特定の期間。
さらに、sleepはThreadクラスの静的メソッドであり、スレッドで動作しますが、wait()はObjectクラスにあり、オブジェクトで呼び出されます。
別のポイントとして、あるオブジェクトでwaitを呼び出すと、関連するスレッドがオブジェクトを同期してから待機します。 :)
この投稿から: http://javaconceptoftheday.com / difference-between-wait-and-sleep-methods-in-java /
wait()メソッド。
1)wait()メソッドを呼び出すスレッドは、保持しているロックを解除します。
2)他のスレッドが同じロックでnotify()またはnotifyAll()メソッドを呼び出した後、スレッドはロックを取り戻します。
3)同期ブロック内でwait()メソッドを呼び出す必要があります。
4)オブジェクトに対してwait()メソッドが常に呼び出されます。
5)待機中のスレッドは、notify()またはnotifyAll()メソッドを呼び出すことにより、他のスレッドによってウェイクアップできます。
6)wait()メソッドを呼び出すには、スレッドにオブジェクトロックが必要です。
sleep()メソッド
1)sleep()メソッドを呼び出すスレッドは、保持しているロックを解除しません。
2)sleep()メソッドは、同期ブロックの内部または外部で呼び出すことができます。
3)スレッドでsleep()メソッドが常に呼び出されます。
4)スリープ状態のスレッドは、他のスレッドによってウェイクアップすることはできません。そうすると、スレッドはInterruptedExceptionをスローします。
5)sleep()メソッドを呼び出すには、スレッドがオブジェクトをロックする必要はありません。
-
wait()
は、Object
クラスのメソッドです。
sleep()
は、Thread
クラスのメソッドです。 -
sleep()
により、スレッドはxミリ秒間sleep
状態になります。
スレッドがスリープ状態になると、ロックは解除されません
。 -
wait()
により、スレッドはロックを解除し、サスペンド状態になります
。
このスレッドは、notify()
またはnotifAll()
メソッドが 同じオブジェクトに対して呼び出されます。
スリープ/割り込みと待機/通知の潜在的な大きな違いの1つは、
-
を呼び出す = "nofollow">
は常に例外をスローします(例: InterruptedException )、一方sleep()
-
を呼び出す = "nofollow">
はサポートしていません。wait()
不要なときに例外を生成するのは非効率的です。スレッドが高速で相互に通信している場合、常に割り込みを呼び出すと多くの例外が生成されます。これはCPUの総無駄です。
あなたは正しい-Sleep()はそのスレッドを「スリープ」させる。そして、CPUがオフになり、他のスレッド(コンテキストスイッチングとも呼ばれます)を処理しますが、WaitはCPUが現在のスレッドを処理し続けると信じています。
両方使用していますCPUサイクルでスレッドを切り替えるには、スレッドが数ミリ秒間何もしないようにするだけです。
また、スリープはコンテキストの切り替えを強制することに注意してください。
また-一般に、コンテキストの切り替えを制御することはできません-待機中、OSは他のスレッドを処理することを選択できます(そして、より長い待機の場合)。
メソッドはさまざまな目的に使用されます。
Thread.sleep(5000); // Wait until the time has passed.
Object.wait(); // Wait until some other thread tells me to wake up.
Thread.sleep(n) は中断できますが、Object.wait()は 通知する必要があります。
待機する最大時間を指定することができます: Object.wait(5000)
ので、 wait
を使用して、 sleep
を実行できます。しかし、ロックを気にする必要があります。
どちらのメソッドも、スリープ/待機中にCPUを使用しません。
メソッドはネイティブコードを使用して実装され、同様の構成要素を使用しますが、同じ方法ではありません。
自分自身を探してください:ネイティブメソッドのソースコードは利用可能ですか? ファイル /src/share/vm/prims/jvm.cpp
は出発点です...
ここで、wait()は、別のスレッドから通知されるまで待機状態になりますが、sleep()にはしばらく時間がかかります。その後、自動的にReady状態に移行します...
Wait()とsleep()の違い?
Thread.sleep() 作業が完了すると、全員にロックが解除されます。誰にもロックが解除されなくなるまで。
Sleep() take the key, its never release the key to anyone, when its work completed then only its release then only take the key waiting stage threads.
Object.wait() 待機段階に移行すると、キーがリリースされ、パラメータに基づいて数秒間待機します。
例:
あなたはあなたの右手でコーヒーを飲んでいます。同じ手の別の誰かを連れて行くことができます。また。これはsleep()です あなたは仕事をしていなかった睡眠時間、あなたは睡眠だけをしている..ここでも同じ。
wait()。あなたが待っている間に、あなたが置かれて別の手段を取るとき、それは待っています
映画またはあなたのシステムで何かをプレイしているプレイヤーと同じものを一度に複数プレイすることはできません、それはここにあります。 >
wait
はロックを解除し、 sleep
は解除しません。待機状態のスレッドは、 notify
または notifyAll
が呼び出されるとすぐに起動できます。ただし、 sleep
の場合、スレッドはロックを保持し、スリープ時間が経過した後にのみ対象となります。
sleep()
メソッドは、現在のスレッドを指定された時間、実行状態からブロック状態に移行させます。現在のスレッドがオブジェクトのロックを保持している場合、それは保持し続けます。つまり、他のスレッドはそのクラスオブジェクトの同期メソッドを実行できません。
wait()
メソッドは、指定された時間または通知まで現在のスレッドをブロック状態にしますが、この場合、スレッドはオブジェクトのロックを解除します(つまり、他のスレッド呼び出し元オブジェクトの同期メソッドを実行できます。
私の意見では、両方のメカニズムの主な違いは、スリープ/割り込みがスレッドを処理する最も基本的な方法であるのに対して、待機/通知はスレッド相互通信を容易にすることを目的とした抽象化であるこれは、スリープ/割り込みは何でもできるが、この特定のタスクは実行が難しいことを意味します。
待機/通知が適しているのはなぜですか?個人的な考慮事項を次に示します。
-
集中化を強制します。単一の共有オブジェクトを使用してスレッドのグループ間の通信を調整できます。これにより、作業が大幅に簡素化されます。
-
同期を強制します。同期ブロックで待機/通知の呼び出しをプログラマにラップさせるためです。
-
スレッドの起源と番号には依存しません。このアプローチを使用すると、他のスレッドを編集したり、既存のスレッドを追跡したりせずに、任意にスレッドを追加できます。スリープ/割り込みを使用した場合は、最初にスリープ中のスレッドへの参照を保持してから、それらを1つずつ手動で割り込む必要があります。
これを説明するのに適した実生活の例は、古典的なレストランと従業員がそれらの間で通信するために使用する方法です:ウェイターは顧客のリクエストを中央の場所(コルクボード、テーブルなど)に残します。)、ベルを鳴らすと、キッチンの労働者がそのような要求を取りに来ます。コースの準備が整ったら、キッチンの担当者がベルを再度鳴らし、ウェイターが認識して顧客に届けるようにします。
スリープに関する例ではロックを解除して待機しません
ここには2つのクラスがあります:
- Main :mainメソッドと2つのスレッドが含まれます。
-
シングルトン:これは、2つの静的メソッドgetInstance()およびgetInstance(boolean isWait)を持つシングルトンクラスです。
public class Main { private static Singleton singletonA = null; private static Singleton singletonB = null; public static void main(String[] args) throws InterruptedException { Thread threadA = new Thread() { @Override public void run() { singletonA = Singleton.getInstance(true); } }; Thread threadB = new Thread() { @Override public void run() { singletonB = Singleton.getInstance(); while (singletonA == null) { System.out.println("SingletonA still null"); } if (singletonA == singletonB) { System.out.println("Both singleton are same"); } else { System.out.println("Both singleton are not same"); } } }; threadA.start(); threadB.start(); } }
and
public class Singleton {
private static Singleton _instance;
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
public static Singleton getInstance(boolean isWait) {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null) {
if (isWait) {
try {
// Singleton.class.wait(500);//Using wait
Thread.sleep(500);// Using Sleep
System.out.println("_instance :"
+ String.valueOf(_instance));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
_instance = new Singleton();
}
}
}
return _instance;
}
}
この例を実行すると、以下の出力が得られます:
_instance :null
Both singleton are same
ここでは、threadAとthreadBによって作成されたシングルトンインスタンスは同じです。これは、threadAがロックを解除するまでthreadBが外部で待機していることを意味します。
Thread.sleep(500)にコメントして、Singleton.javaを変更します。メソッドとコメント解除Singleton.class.wait(500); 。これは、Singleton.class.wait(500)のためです。メソッドthreadAはすべての獲得ロックを解放し、&#8220;非実行可能&#8221;に移動します。状態、threadBは、同期ブロックに入るための変更を取得します。
もう一度実行します:
SingletonA still null
SingletonA still null
SingletonA still null
_instance :com.omt.sleepwait.Singleton@10c042ab
SingletonA still null
SingletonA still null
SingletonA still null
Both singleton are not same
threadAとthreadBによって作成されたシングルトンインスタンスは、threadBが同期ブロックに入るように変更され、500ミリ秒後にthreadAが最後の位置から開始し、もう1つのシングルトンオブジェクトを作成したため、同じではありません。
同期ブロックから呼び出す必要があります: wait()
メソッドは常に同期ブロックから呼び出されます。つまり、 wait()
メソッドはオブジェクトをロックする必要があります呼び出されるオブジェクトの前に監視します。ただし、 sleep()
メソッドは同期ブロックの外部から呼び出すことができます。つまり、 sleep()
メソッドはオブジェクトモニターを必要としません。
IllegalMonitorStateException: IllegalMonitorStateException
が実行時にスローされるが、 sleep( )
メソッドはこのような例外をスローしません。
所属するクラス: wait()
メソッドは java.lang.Object
クラスに属しますが、 sleep()
メソッドは java.lang.Thread
クラスに属します。
オブジェクトまたはスレッドで呼び出される: wait()
メソッドはオブジェクトで呼び出されますが、 sleep()
メソッドはオブジェクトではなくスレッドで呼び出されます。
スレッド状態:オブジェクトで wait()
メソッドが呼び出されると、オブジェクトのモニターを保持しているスレッドは実行状態から待機状態になり、実行可能に戻ることができますそのオブジェクトで notify()
または notifyAll()
メソッドが呼び出された場合にのみ状態を示します。そして、後のスレッドスケジューラは、そのスレッドを実行可能状態から実行状態に移行するようにスケジュールします。
sleep()
がスレッドで呼び出されると、実行状態から待機状態になり、スリープ時間が経過すると実行可能状態に戻ることができます。
同期ブロックから呼び出された場合: wait()
メソッドが呼び出された場合、スレッドはオブジェクトのロックを解除します。ただし、同期ブロックまたはメソッドスレッドから呼び出された sleep()
メソッドは、オブジェクトロックを保持しません。
詳細リファレンス
waitのOracleドキュメントページから() Object
のメソッド:
public final void wait()
- 別のスレッドがこのオブジェクトの
notify()
メソッドまたはnotifyAll()
メソッドを呼び出すまで、現在のスレッドを待機させます。つまり、このメソッドは、単にwait(0)
の呼び出しを実行するかのように動作します。 - 現在のスレッドは、このオブジェクトのモニターを所有している必要があります。スレッドはこのモニターの所有権を解放し、別のスレッドがこのオブジェクトのモニターでウェイクアップするのを待機しているスレッドに通知するまで待機します
- 割り込みと偽のウェイクアップが可能です
- このメソッドは、このオブジェクトのモニターの所有者であるスレッドによってのみ呼び出される必要があります
このメソッドはスローします
-
IllegalMonitorStateException
-現在のスレッドがオブジェクトのモニターの所有者でない場合。 -
InterruptedException
-現在のスレッドが通知を待機する前または待機中に現在のスレッドを中断したスレッドがある場合。この例外がスローされると、現在のスレッドの割り込みステータスはクリアされます。
のOracleドキュメントページから Thread
クラスのsleep()メソッド:
public static void sleep(long millis)
- システムタイマーとスケジューラの精度と精度に応じて、指定されたミリ秒数の間、現在実行中のスレッドをスリープ(一時的に実行を停止)します。
- スレッドはモニターの所有権を失いません。
このメソッドは以下をスローします:
-
IllegalArgumentException
-millisの値が負の場合 -
InterruptedException
-スレッドが現在のスレッドを中断した場合。この例外がスローされると、現在のスレッドの割り込みステータスはクリアされます。
その他の重要な違い:
wait()
は、静的メソッド sleep()
(クラスメソッド)とは異なり、非静的メソッド(インスタンスメソッド)です。
wait()
は同期メソッド内で提供されます
一方、 wait()
メソッドはオブジェクトのロックを解除しますが、 sleep()
または< code> yield()は lock()
をリリースします。
waitは、タイムアウト値が経過すると起動するか、どちらか早い方に通知します(または割り込みもできます)。タイムアウト値のないwait()は、通知または中断されるまでずっと待機します
- メソッド
wait(1000)
は、現在のスレッドを最大1秒スリープさせます。- スレッドが
notify()
またはnotifyAll()
メソッド呼び出し。
- スレッドが
-
sleep(1000)
は、現在のスレッドを正確に1秒間スリープさせます。- また、スリープ中のスレッドはリソースをロックしません。ただし、待機スレッドは実行します。