スレッドに深く入り込むwait()とnotify()
3015 ワード
public class ThreadA {
public static void main(String[] args) {
ThreadB b = new ThreadB();
b.start();
System.out.println("b is start....");
synchronized (b)// b , ?
{
try {
System.out.println("Waiting for b to complete...");
b.wait();// , wait?
System.out.println("Completed.Now back to main thread");
} catch (InterruptedException e) {
}
}
System.out.println("Total is :" + b.total);
}
}
class ThreadB extends Thread {
int total;
public void run() {
synchronized (this) {
System.out.println("ThreadB is running..");
for (int i = 0; i < 100; i++) {
total += i;
System.out.println("total is " + total);
}
notify();
}
}
}
このプログラムを分析するには、まずnotify()とwait()を理解しなければならない.なぜ、先日スレッドを記録したときにこの2つの方法を記録しなかったのか.この2つの方法はもともとThreadクラスではなく、最下位のobjectベースクラスに属しているからだ.つまり、Threadだけでなく、各オブジェクトにnotifyとwaitの機能があるからだ.なぜだろうか.ロックを操作するために使用されるため、各オブジェクトにはロックがあり、ロックは各オブジェクトの基礎であり、ロックが基礎である以上、ロックを操作する方法も当然最も基礎である.
さらに下を見る前に、まずThink in Javaの14.3.1の第3部の内容を復習したほうがいいです.待機と通知、つまりwait()とnotifyです.
Think in Javaの説明に従って、「wait()はスレッドを「睡眠」状態に置くことを許可し、同時に「積極的に」条件の変化を待つことができる.また、1つのnotify()またはnotifyAll()が変化した場合にのみ、スレッドが呼び覚まされ、エントリが変化しているかどうかを確認する.」
この言葉を説明しましょう.
「wait()は、スレッドを「睡眠」状態に置くことを可能にする、すなわち、waitも現在のスレッドをブロックする点であり、sleepまたはsuspendと同じである.ではsleep、suspendと何が違いますか?
違いは「(wait)同時に」積極的に「条件の変化を待つ」ことであり、sleepとsuspendはできない.同期(synchronized)の助けによってスレッド間の衝突を防止する必要がある場合があるため、同期を使用すると、オブジェクトをロックする、すなわちオブジェクトロックを取得し、他のオブジェクトロックを使用するスレッドは、同期方法または同期ブロック内のプログラムがすべて実行されるまで待つしかない.同期方法と同期ブロックでは、sleep()もsuspend()も自分が呼び出されたときにロックを解除することは不可能であり、彼らは使用中のオブジェクトロックを占領して放さない.
waitは、同期メソッドまたは同期ブロックにオブジェクトロックを一時的に放棄させ、他のオブジェクトロックが必要な人(ここではプログラムブロックまたはスレッド)に一時的に譲ることができます.これは、wait()の実行中にスレッドオブジェクト内の他の同期メソッドを呼び出すことができることを意味します.他の場合(sleepとかsuspendとか)、これは不可能です.
しかし、私が前に言ったように、オブジェクトロックを一時的に放棄し、他のスレッドに一時的に使用するだけで、私のwaitがいるスレッドはこのオブジェクトロックを回収しなければなりません.何だ?wait他の人が使い終わったら返してください.
では、どうやって相手の鍵を取り戻しますか?
第1の方法は、借りる時間を限定する.wait()にパラメータを設定します.例えばwait(1000)はミリ秒単位で、1秒しか借りていないことを示しています.1秒後、自動的に回収します.
2つ目の方法は、借りた人に知らせてください.彼は使い終わったので、返してください.この时、私はすぐに回収します.まあ、もし私が1時間設定して回収して、他の人は30分で終わったら、どうしますか?*!もちろん使い終わったら回収します.私が設置した時間はどのくらいですか.
では、他の人はどのように私に知らせますか?皆さんも考えられると思いますが、notify()は、これが最後の一言です.「そして、1つのnotify()やnotifyAll()が変化したときだけ、スレッドが呼び覚まされる」という意味です.
したがって、そのクラスでスレッドに関する処理を準備するかどうかにかかわらず、wait()とnotify()を任意の同期方法または同期ブロックの内部に配置することができる.また、実際には、同期方法や同期ブロックでwait()とnotify()を呼び出すしかない.
この時、私たちは上のプログラムを説明して、まるで手のひらを返すように簡単です.
synchronized(b){...};bをリソースロックとして使用する同期ブロックを定義することを意味する.b.wait();ロックを一時的に解放する、現在のスレッドをブロックし、他の同じロックを使用するスレッドが実行する機会を与えることを意味するが、ここで同じロックを使用するのはbスレッド自体である.このスレッドは、ある場所に実行する後にnotify()でwaitのスレッドに通知し、ロックが切れ、notify()が存在する同期ブロックが実行する後、waitが存在するスレッドは実行を継続することができる.