違いは何であるwait()
とsleep()
スレッドでは?
wait()
-ingスレッドはまだ実行モードにあり、CPUサイクルを使用していますが、sleep()
-ingはCPUサイクルを消費しないという理解は正しいですか?
なぜ両方が wait()
ありsleep()
、それらの実装は下位レベルでどのように異なるのですか?
違いは何であるwait()
とsleep()
スレッドでは?
wait()
-ingスレッドはまだ実行モードにあり、CPUサイクルを使用していますが、sleep()
-ingはCPUサイクルを消費しないという理解は正しいですか?
なぜ両方が wait()
ありsleep()
、それらの実装は下位レベルでどのように異なるのですか?
回答:
A は、待機中のモニターをwait
呼び出す別のスレッドによって「起こす」ことができますnotify
が、sleep
できません。また、wait
(およびnotify
)はsynchronized
、モニターオブジェクトのブロックで発生する必要がありますが、発生sleep
しません。
Object mon = ...;
synchronized (mon) {
mon.wait();
}
この時点で、現在実行中のスレッドは待機し、モニターを解放します。別のスレッドが行う可能性があります
synchronized (mon) { mon.notify(); }
(同じに mon
オブジェクト上で)最初のスレッド(モニターで待機している唯一のスレッドであると想定)が起動します。
notifyAll
モニターで複数のスレッドが待機している場合も呼び出すことができます。これにより、すべてのスレッドが起動します。ただし、モニターを取得できるスレッドは1つだけです(これwait
は、synchronized
ブロックことに注意)、続行できます。残り、モニターのロックを取得できるまでブロックされます。
もう一つのポイントは、あなたが呼び出すことであるwait
にObject
呼び出すのに対し(つまり、あなたがオブジェクトのモニターで待つこと)自体sleep
にThread
。
さらに別のポイントは、あなたが得ることができるということであるスプリアスウェイクアップからwait
(明らかな理由もなく履歴書を待っている、すなわちスレッドを)。次のように、常にwait
何らかの条件で回転している必要があります。
synchronized {
while (!condition) { mon.wait(); }
}
wait
/ notify
は通常、他のスレッドがタスクを完了するのを待つか、特定の条件が満たされるまで待つために使用されます。
まだ言及されていない主な違いの1つは、スレッドのスリープ中はスレッドが保持しているロックを解放しませんが、待機中wait()
は呼び出されたオブジェクトのロックを解放します。
synchronized(LOCK) {
Thread.sleep(1000); // LOCK is held
}
synchronized(LOCK) {
LOCK.wait(); // LOCK is not held
}
sleep
保持していると主張していますが、そうではありません。公平に比較するために、と比較すると、両方の命令でが解放されないことがわかります。違いがある場合、それは明示的にJavaロックを使用していないと言えますが、問題は「実装の下位レベルでの変化はどのようにあるのか」ということです。引用しない。synchronized(OUTER_LOCK){ Thread.sleep(1000); }
synchronized(OUTER_LOCK){ synchronized(LOCK){LOCK.wait();} }
OUTER_LOCK
sleep
wait()
は、それが呼び出される最も内側のロックの状態に関連付けられており、コード例でwait()
は、解放のみが可能で、解放はできLOCK
ませんOUTER_LOCK
。とにかく、Javaモニターはこのように設計されています。公正な比較はとにsynchronized(OUTER_LOCK){ synchronized(LOCK) { Thread.sleep(1000); } }
なりsynchronized(OUTER_LOCK){ synchronized(LOCK) { LOCK.wait(); } }
ます。この場合sleep()
、両方のロックが保持wait()
されますLOCK
が、解放されますが保持されますOUTER_LOCK
私が見つかりました。この記事は役に立ちます。それは違いますThread.sleep()
、Thread.yield()
と、Object.wait()
人間の言葉では。引用するには:
最終的には、タイムスライスをプロセスとスレッドに渡すOSのスケジューラにまで到達します。
sleep(n)
言う 「私は自分のタイムスライスで終わりだ、と私に少なくともnミリ秒のために別のものを与えないでください。」OSは、要求された時間が経過するまで、スリープ状態のスレッドをスケジュールすることすらしません。
yield()
言う 「私は私のタイムスライスで終わりだが、私はまだやるべき仕事を持っています。」OSは、スレッドに別のタイムスライスをすぐに与えたり、他のスレッドを与えたり、CPUを処理したりするスレッドを放棄したりできます。
wait()
言う私は私のタイムスライスで終わりです」。誰かがnotify()を呼び出すまで、別のタイムスライスを与えないでください。」と同様sleep()
に、OSは、誰かが呼び出さない限りnotify()
(または他のいくつかのウェイクアップシナリオの1つが発生した場合)、タスクのスケジュールを設定しません。スレッドは、ブロッキングIOを実行するとき、および他のいくつかの状況下で、残りのタイムスライスも失います。スレッドがタイムスライス全体で機能する場合、OSは大まかに強制的に制御を取得します。
yield()
呼び出さ他のプロセスが実行できるようにします。必要
yield()
になることはめったにありませんが、論理的なタスク境界を備えたコンピューティング負荷の高いアプリがある場合、挿入することでシステムの応答yield()
性が向上する可能性があります(時間を犠牲にして、OSだけでなくOSへのコンテキスト切り替えも無料ではありません)。いつものように、気になる目標を測定してテストします。
sleep(n)
は、現在実行中のスレッドがロックのモニターを自発的に放棄していると暗黙的に述べられていますが、これは正しくありません。スレッドのjavadocからの引用:「スレッドはモニターの所有権を失うことはありません。」
sleep
ていません。これは、他のJavaメソッド呼び出しよりもモニターに関して特別な動作がないためです。つまり、どのような方法でもモニターと対話したり変更したりすることはありません。モニターについて何か言う場合wait
は、上記の内容に加えて、呼び出されたオブジェクトのロックを一時的に放棄することを指定する必要があります。
wait(n)
と比較するために使用しsleep(n)
ます。引数なしのものを使用して比較しても意味がありません。
ここには多くの答えがありますが、言及されている意味上の違いは見つかりませんでした。
それはスレッド自体に関するものではありません。非常に異なるユースケースをサポートするため、両方の方法が必要です。
sleep()
以前と同じようにスレッドをスリープ状態に送信し、コンテキストをパックして、事前定義された時間だけ実行を停止します。したがって、期限内にそれを起こすためには、スレッド参照を知る必要があります。これは、マルチスレッド環境では一般的な状況ではありません。これは主に、時刻同期(たとえば、正確に3.5秒でスリープ解除)および/またはハードコードされた公平性(しばらくスリープして、他のスレッドを機能させる)に使用されます。
wait()
逆に、はスレッド(またはメッセージ)の同期メカニズムであり、参照を保存していない(注意していない)スレッドに通知できます。これは、パブリッシュ/サブスクライブパターン(wait
==サブスクライブおよびnotify()
==パブリッシュ)と考えることができます。基本的にnotify()を使用すると、メッセージを送信します(まったく受信されないこともあり、通常は気にしません)。
要約すると、通常sleep()
は時刻同期とwait()
マルチスレッド同期に使用します。
それらは、基盤となるOSで同じ方法で実装することも、まったく実装しないこともできます(以前のバージョンのJavaには実際のマルチスレッドがなかったため、おそらく一部の小さなVMではそれもできません)。JavaがVM上で実行されることを忘れないでください。そのため、コードは、Javaが実行されるVM / OS / HWに応じて異なるものに変換されます。
ここでは、wait()
とsleep()
メソッドのいくつかの重要な違いを示しました。
PS: また、リンクをクリックしてライブラリコードを確認してください(内部での作業、理解を深めるために少し遊んでみてください)。
wait()
メソッドはロックを解放します。 wait()
Object
クラスのメソッドです。wait()
非静的な方法です- public final void wait() throws InterruptedException { //...}
wait()
notify()
またはnotifyAll()
メソッドによって通知される必要があります。wait()
メソッドは、誤警報を処理するためにループから呼び出される必要があります。
wait()
メソッドは、同期されたコンテキスト(つまり、同期されたメソッドまたはブロック)から呼び出す必要があります。それ以外の場合はスローされます IllegalMonitorStateException
sleep()
メソッドはロックを解放しません。sleep()
java.lang.Thread
クラスのメソッドです。sleep()
静的メソッドです- public static void sleep(long millis, int nanos) throws InterruptedException { //... }
sleep()
完了します。sleep()
ループから呼び出さない方がよい(つまり、以下のコードを参照)。sleep()
どこからでも呼び出すことができます。特定の要件はありません。参照:待機とスリープの違い
待機およびスリープメソッドを呼び出すためのコードスニペット
synchronized(monitor){
while(condition == true){
monitor.wait() //releases monitor lock
}
Thread.sleep(100); //puts current thread on Sleep
}
Thread.sleep()
プロセッサ時間を他のスレッドで利用できるようにするために使用されます。スリープ期間は、割り込みによって(つまり、JVMによって)終了できます。このstackoverflow.com/questions/4264355/…
notify()
またはnotifyAll()
あるObject
クラスのメソッド。したがって、これらはすべてのクラスのオブジェクト(つまり、ここではThread
クラスも含む)で使用できます。コードの参照grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/...
待機とスリープに取り組んだ後に結論するいくつかの主な違いはあります。まず、wait()とsleep()を使用してサンプルを見てください。
例1:待機()およびスリープ()の使用:
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();
}
いくつかのキーノートを明確にしましょう:
通常、時間の同期にはsleep()を使用し、マルチスレッドの同期にはwait()を使用します。
私が間違っている場合は修正してください。
根本的な違いは、あるwait()
からであるObject
とsleep()
の静的メソッドですThread
。
主な違いは、待機中にロックが解放されずwait()
、ロックsleep()
が解放されないことです。
wait()
スレッド間の通信にsleep()
使用されますが、一般的には、実行の一時停止を導入するために使用されます。
wait()
同期の内部から呼び出す必要があります。そうしないとを取得IllegalMonitorStateException
しsleep()
ますが、どこからでも呼び出すことができます。
wait()
、notify()
またはを呼び出す必要がありnotifyAll()
ます。sleep(),
スレッドに関しては、指定された時間間隔の後に開始されます。これは非常に単純な質問です。これらの方法は両方ともまったく異なる使い方をしているためです。
主な違いは、スリープ中にロックまたはモニターが解放されるのを待たずに待機することです。待機はスレッド間の通信に使用され、スリープは実行の一時停止を導入するために使用されます。
これは明確で基本的な説明にすぎません。それ以上の情報が必要な場合は、読み続けてください。
以下の場合はwait()
、メソッドスレッド待ち状態になり、私たちが呼ぶまでは、自動的に戻ってこないだろうnotify()
方法を(またはnotifyAll()
あなたが待機状態にもっとしてスレッドを1つ持っていて、それらのスレッドの全てを覚ますしたい場合)。また、wait()
またはnotify()
またはnotifyAll()
メソッドにアクセスするには、同期ロック、オブジェクトロック、またはクラスロックが必要です。そしてもう1つ、このwait()
メソッドはスレッド間通信に使用されます。これは、スレッドが待機状態になった場合、別のスレッドがそのスレッドをウェイクアップする必要があるためです。
しかし、sleep()
この場合、プロセスを数秒間または必要な時間だけ保持するために使用される方法です。スレッドを取り戻すために、メソッドnotify()
やnotifyAll()
メソッドを呼び出す必要がないからです。または、そのスレッドをコールバックするために他のスレッドを必要としません。たとえば、ユーザーの番後のゲームのように、数秒後に何かが発生したい場合は、コンピューターが再生されるまでユーザーに待機させたい場合は、sleep()
メソッドに言及できます。
インタビューでよく聞かれるもう1つの重要な違いsleep()
は、Thread
クラスにwait()
属していることとObject
クラスに属していることです。
これらは、間のすべての違いですsleep()
とwait()
。
また、両方のメソッドには類似点があります。どちらもチェックされたステートメントであるため、これらのメソッドにアクセスするにはキャッチまたはスローを試す必要があります。
これがお役に立てば幸いです。
ソース:http : //www.jguru.com/faq/view.jsp?EID=47127
Thread.sleep()
現在のスレッドをしばらくの間「実行不可」状態にします。スレッドは、取得したモニターを保持します。つまり、スレッドが現在同期ブロックまたはメソッド内にある場合、他のスレッドはこのブロックまたはメソッドに入ることはできません。別のスレッドが呼び出すt.interrupt()
と、スリープ状態のスレッドが起動します。sleepは静的メソッドであることに注意してください。つまり、現在のスレッド(sleepメソッドを実行しているスレッド)に常に影響します。よくある間違いは
t.sleep()
、tが別のスレッドである場合に呼び出すことです。それでも、スリープするのは現在のスレッドであり、tスレッドではありません。
t.suspend()
廃止予定です。これを使用すると、現在のスレッド以外のスレッドを停止することができます。中断されたスレッドはすべてのモニターを保持し、この状態は中断できないため、デッドロックが発生しやすくなります。
object.wait()
のように現在のスレッドを「実行不可」状態にsleep()
しますが、ひねりを加えています。スレッドではなくオブジェクトで待機が呼び出されます。このオブジェクトを「ロックオブジェクト」と呼びます。lock.wait()
が呼び出される前に、現在のスレッドはロックオブジェクトで同期する必要があります。wait()
次に、このロックを解放し、ロックに関連付けられている「待機リスト」にスレッドを追加します。その後、別のスレッドが同じロックオブジェクトで同期してを呼び出すことができますlock.notify()
。これにより、元の待機中のスレッドが起動します。基本的に、wait()
/notify()
はsleep()
/interrupt()
に似 ています。アクティブなスレッドのみが、スリープ状態のスレッドへの直接ポインタを必要とせず、共有ロックオブジェクトへのポインタのみを必要とします。
待機とスリープは2つの異なるものです。
sleep()
、スレッド指定された期間のために働いて停止します。wait()
、オブジェクトビーイングが待っていた-になるまで、一般的に他のスレッドによって、通知されたスレッド動作を停止します。sleep
停止させたい場合、wait
/ から他の入力が送られるまでスレッドを停止させたい場合notify
。interrupt
スレッドの実行を停止して終了するようにスレッドに通知する方法として意図されています。これはによって処理されますがsleep
、wait
I / O関数もブロックされます(メソッドを呼び出すことにより、同じ動作の関数を実装できますThread.interrupted()
)。パフォーマンスに関しては、機能は通常、設計された目標に合わせて最適化されています。
睡眠()は、数秒間または必要な時間プロセスを保持するために使用されるメソッドですが、wait()メソッドの場合、スレッドは待機状態になり、notify()を呼び出すまで自動的に復帰しません。 notifyAll()。
主な違いは、wait()がロックまたはモニターを解放する一方で、sleep()は待機中にロックまたはモニターを解放しないことです。待機はスレッド間の通信に使用され、スリープは通常、実行の一時停止を導入するために使用されます。
Thread.sleep()は、現在のスレッドをしばらくの間「実行不可」状態にします。スレッドは取得したモニターを保持します。つまり、スレッドが現在同期ブロックまたはメソッド内にある場合、他のスレッドはこのブロックまたはメソッドに入ることはできません。別のスレッドがt.interrupt()を呼び出すと、スリープ状態のスレッドが起動します。sleepは静的メソッドであることに注意してください。つまり、現在のスレッド(sleepメソッドを実行しているスレッド)に常に影響します。よくある間違いは、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
}
上記のすべてのポイントを分類してみましょう:
Call on:
Synchronized:
Hold lock:
Wake-up condition:
Usage:
簡単に言えば、待機は他のスレッドがあなたを呼び出すまで待機するのに対し、スリープは指定された期間、「次のステートメントを実行しない」です。
さらに、sleepはThreadクラスの静的メソッドであり、スレッドで動作しますが、wait()はObjectクラスであり、オブジェクトで呼び出されます。
別のポイントとして、いくつかのオブジェクトでwaitを呼び出すと、関連するスレッドがオブジェクトを同期してから待機します。:)
wait
そしてsleep
方法は非常に異なります:
考えてみると、名前はその点で混乱しています。ただしsleep
、標準的な名前であり、Win API やのwait
ようなものです。WaitForSingleObject
WaitForMultipleObjects
この投稿から:http : //javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/
1)wait()メソッドを呼び出すスレッドは、保持しているロックを解放します。
2)他のスレッドが同じロックでnotify()またはnotifyAll()メソッドを呼び出した後、スレッドはロックを取り戻します。
3)wait()メソッドは、同期されたブロック内で呼び出す必要があります。
4)wait()メソッドは常にオブジェクトで呼び出されます。
5)待機中のスレッドは、notify()またはnotifyAll()メソッドを呼び出すことにより、他のスレッドによって起こされることができます。
6)wait()メソッドを呼び出すには、スレッドにオブジェクトロックが必要です。
1)sleep()メソッドを呼び出すスレッドは、保持しているロックを解放しません。
2)sleep()メソッドは同期ブロック内または同期ブロック外で呼び出すことができます。
3)sleep()メソッドは常にスレッドで呼び出されます。
4)スリープ状態のスレッドは、他のスレッドによって起こされることはありません。その場合、スレッドはInterruptedExceptionをスローします。
5)sleep()メソッドを呼び出すために、スレッドはオブジェクトをロックする必要はありません。
スリープ/割り込みと待機/通知の大きな違いの1つは、
interrupt()
中に呼び出しを行うと、sleep()
常に例外がスローされます(例:InterruptedException)。notify()
中に呼び出しは行いwait()
ません。不要なときに例外を生成するのは非効率的です。スレッドが互いに高速で通信している場合、割り込みを常に呼び出していると、多くの例外が発生します。これは、CPUの浪費です。
あなたが正しい-Sleep()はそのスレッドを「スリープ」させ、CPUがオフになり、他のスレッド(コンテキストスイッチングとも呼ばれます)を処理します。
CPUを使用していないときに他の人にCPUを使用させるのは理にかなっているように見えるかもしれませんが、実際には、コンテキストの切り替えにオーバーヘッドが発生します。スレッドを切り替えるよりも、数ミリ秒間スレッドが何もしないようにするだけです。
また、スリープはコンテキストの切り替えを強制することに注意してください。
また、一般に、コンテキストの切り替えを制御することはできません。待機中に、OSは他のスレッドを処理することを選択できます(待機時間が長くなると)。
interrupt
です。終了時刻はn
ですwait(n)
。¶¶もう8年になりますが、まだ誰も答えを出していません。
メソッドはさまざまな目的で使用されます。
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
、to、er を使用することは可能sleep
ですが、ロックに煩わされる必要があります。
どちらの方法も、スリープ/待機中にCPUを使用しません。
これらのメソッドは、ネイティブコードを使用して実装されますが、同様の構成を使用しますが、同じ方法ではありません。
あなた自身を探してください:ネイティブメソッドのソースコードは利用できますか?ファイル/src/share/vm/prims/jvm.cpp
が出発点です...
Thread.sleep(big_num)
中断する必要があります。通知Object.wait(small_num)
することができます。
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
ロックを解放し、解放しsleep
ません。待機状態のスレッドは、notify
またはnotifyAll
呼び出されるとすぐに起動することができます。ただしsleep
、スレッドがロックを保持している場合は、スリープ時間が経過した後でのみ適格になります。
InterruptedException
は、Javadocで言うようにスローされます。
私の意見では、両方のメカニズムの主な違いは、スリープ/割り込みがスレッドを処理する最も基本的な方法であるのに対し、待機/通知はスレッドの相互通信を容易にすることを目的とした抽象化です。これは、スリープ/割り込みが何でもできることを意味しますが、この特定のタスクは実行するのがより困難です。
待機/通知の方が適しているのはなぜですか?ここにいくつかの個人的な考慮事項があります:
集中化を実施します。単一の共有オブジェクトを使用して、スレッドのグループ間の通信を調整できます。これにより、作業が大幅に簡略化されます。
同期を実行します。プログラマが待機/通知の呼び出しを同期ブロックにラップするためです。
スレッドの原点と番号には依存しません。このアプローチを使用すると、他のスレッドを編集したり、既存のスレッドを追跡したりすることなく、任意にスレッドを追加できます。スリープ/割り込みを使用した場合は、まずスリープ中のスレッドへの参照を保持し、次に手動でそれらを1つずつ割り込みする必要があります。
これを説明するのに良い実生活の例は、古典的なレストランと、スタッフがそれらの間で通信するために使用する方法です。ウェイターは顧客の要求を中央の場所(コルクボード、テーブルなど)に置きます。ベルを鳴らすと、キッチンの作業員がそのようなリクエストに応じます。コースの準備が整うと、キッチンの担当者が再びベルを鳴らしてウェイターが気づき、お客様に案内します。
スリープに関する例はロックを解除せずに待機します
ここには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();
}
}
そして
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はすべての獲得ロックを解放して「Non Runnable」状態に移行し、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:実行時にスローされるwait()
よりもオブジェクトロックを取得せずにメソッドが呼び出された場合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
-現在のスレッドが通知を待機する前または待機中にスレッドが現在のスレッドを中断した場合。この例外がスローされると、現在のスレッドの割り込みステータスがクリアされます。
クラスのsleep()メソッドのOracleドキュメントページからThread
:
public static void sleep(long millis)
このメソッドはスローします:
IllegalArgumentException
-ミリ秒の値が負の場合
InterruptedException
-いずれかのスレッドが現在のスレッドに割り込んだ場合。この例外がスローされると、現在のスレッドの割り込みステータスがクリアされます。
その他の主な違い:
wait()
静的メソッドsleep()
(クラスメソッド)とは異なり、非静的メソッド(インスタンスメソッド)です。
wait(1000)
により、現在のスレッドが最大1秒間スリープします。
notify()
またはnotifyAll()
メソッドの呼び出しを受け取った場合、スレッドは1秒未満しかスリープできませんでした。sleep(1000)
と、現在のスレッドが1秒間だけスリープします。
sleep(1000)
正確に1秒間スリープすることは保証されません。以前に中断される場合があります。
実際、これはすべてJavaドキュメントに明確に記述されています(しかし、私は答えを読んだ後でないと気づきませんでした)。
http://docs.oracle.com/javase/8/docs/api/index.html:
wait()-現在のスレッドは、このオブジェクトのモニターを所有している必要があります。スレッドはこのモニターの所有権を解放し、通知オブジェクトまたはnotifyAllメソッドの呼び出しを通じて、別のスレッドがこのオブジェクトのモニターでウェイクアップするのを待っているスレッドに通知するまで待機します。次に、スレッドは、モニターの所有権を再取得できるまで待機し、実行を再開します。
sleep()-現在実行中のスレッドを、システムタイマーとスケジューラーの精度と精度に応じて、指定されたミリ秒の間スリープ(一時的に実行を停止)させます。スレッドがモニターの所有権を失うことはありません。