JAVA wait()とnotify()について
一.概説
wait,notify,notifyAllメソッドはObjectクラスのメンバー関数であるため,Javaのいずれのオブジェクトもこの3つのメソッドを呼び出すことができる.この3つの方法は主にスレッド間通信に用いられ,複数のスレッドの動作を調整する.JAVAではPV操作やプロセス反発などに関する方法はないことを知っておく必要があります.JAVAのプロセス同期はsynchronizedによって実現され、一般的には複数のスレッドがあるリソースに相互反発してアクセスし、synchronizedで十分ですが、オンラインスレッド間で相互起動する必要がある場合はObject.wait(),Object.nofity()を借りる必要があります.
二.wait関数
例えば、wait関数は「疲れたので、少し休みたいです(同时にこのスレッドは休眠します)、対象のロックを持って行ってください.CPUもあげます」と表しています.1.wait関数を呼び出したスレッドは、他のスレッドが同じオブジェクトのnotifyメソッドまたはnotifyAllメソッドを呼び出すまで待機します(このスレッドはスリープします).オブジェクトのnotifyメソッドまたはnotifyAllメソッドを呼び出す他のスレッドがない場合、スレッドは永遠に待機します.2.起動されても、すぐにオブジェクトのロックが取得されるわけではありません.すなわち、3.wait関数は同期コードブロックで呼び出さなければならない(すなわち、現在のスレッドがオブジェクトのロックを持たなければならない)注意waitはsleepとは異なり、sleepはオブジェクトロックを解放しないが、waitはオブジェクトロックを解放する.
三.notifyとnotifyAllメソッド
例えば、皆さん、気をつけてください.このロックの対象はもうすぐ使いますから、目を覚ましてください.準備してください.すぐにロックを使うことができます.いくつかの点に注意してください:1.otofy/notifyAllメソッドも同期コードブロックで呼び出さなければなりません(つまり、呼び出しスレッドはオブジェクトのロックを持たなければなりません).2.notifyメソッドは待機中のスレッド(誰を呼び出すかは不明!)を呼び覚ますだけで、notifyAllメソッドは待機中のすべてのスレッドを呼び覚ます3.notifyメソッドとnotifyAllメソッドを呼び出すと、現在のスレッドは、ロックの所有権をすぐに放棄するのではなく、現在の同期コードブロックの実行が完了するまでロックを解除する必要があります.4.オブジェクトがwaitメソッドを呼び出さなかった場合、notifyメソッドを呼び出すことは影響しません.
四.例を挙げるとよりよく理解できる
これは比較的古典的な面接問題です:3スレッドでABCを印刷する問題で、Object.wait()、Object.notify()アプリケーションに対する最善の理解です.テーマの要求は以下の通りです:3つのスレッドを創立して、Aスレッドは10回Aを印刷して、Bスレッドは10回Bを印刷して、Cスレッドは10回Cを印刷して、スレッドが同時に運行することを要求して、交互に10回ABCを印刷します.この問題はObjectのwait(),notify()で簡単に解決できる.コードは次のとおりです.
public class MyThreadPrinter implements Runnable { private String name; private Object next; private Object self;
}
public class Main {
}
印刷出力:ABCABCABCABCABCABCABCABCABCABCABCABC
このコードを説明します.
我々の第一の目的は、ThreadA->ThreadB->ThreadC->ThreadAループに従って3つのスレッドを実行することである.それでは良いです:ThreadA印刷の条件:aを取得して、b ThreaddB印刷の条件:bを取得して、c ThreadC印刷の条件:cを取得して、a第1歩:初めにThreadAは先にaを取得して、それからbを取得して、印刷が終わった後に、TheadB:“b資源は私が使い終わったことを知らせて、あなたは早く目が覚めるようにしましょう!”bを先に解放し、aを再解放する第2ステップ:b優先aが解放されるので、ThreadBが先に実行(aが占有され、ThreadCが実行できない)、bを先に取得し、cを取得し、bを印刷し、cを先に解放し、bを再解放する第3ステップ:c優先bが解放されるので、ThreadCが先に実行(bが占有され、ThreadAが実行できない)、cを先に取得し、aを取得し、cを印刷し、aを先に解放する.さらにc.を解放すると、このように一歩一歩順番に実行される.
五.末尾
ここまで話しましょう.みんなに役に立つことを望んでいます.
wait,notify,notifyAllメソッドはObjectクラスのメンバー関数であるため,Javaのいずれのオブジェクトもこの3つのメソッドを呼び出すことができる.この3つの方法は主にスレッド間通信に用いられ,複数のスレッドの動作を調整する.JAVAではPV操作やプロセス反発などに関する方法はないことを知っておく必要があります.JAVAのプロセス同期はsynchronizedによって実現され、一般的には複数のスレッドがあるリソースに相互反発してアクセスし、synchronizedで十分ですが、オンラインスレッド間で相互起動する必要がある場合はObject.wait(),Object.nofity()を借りる必要があります.
二.wait関数
例えば、wait関数は「疲れたので、少し休みたいです(同时にこのスレッドは休眠します)、対象のロックを持って行ってください.CPUもあげます」と表しています.1.wait関数を呼び出したスレッドは、他のスレッドが同じオブジェクトのnotifyメソッドまたはnotifyAllメソッドを呼び出すまで待機します(このスレッドはスリープします).オブジェクトのnotifyメソッドまたはnotifyAllメソッドを呼び出す他のスレッドがない場合、スレッドは永遠に待機します.2.起動されても、すぐにオブジェクトのロックが取得されるわけではありません.すなわち、3.wait関数は同期コードブロックで呼び出さなければならない(すなわち、現在のスレッドがオブジェクトのロックを持たなければならない)注意waitはsleepとは異なり、sleepはオブジェクトロックを解放しないが、waitはオブジェクトロックを解放する.
三.notifyとnotifyAllメソッド
例えば、皆さん、気をつけてください.このロックの対象はもうすぐ使いますから、目を覚ましてください.準備してください.すぐにロックを使うことができます.いくつかの点に注意してください:1.otofy/notifyAllメソッドも同期コードブロックで呼び出さなければなりません(つまり、呼び出しスレッドはオブジェクトのロックを持たなければなりません).2.notifyメソッドは待機中のスレッド(誰を呼び出すかは不明!)を呼び覚ますだけで、notifyAllメソッドは待機中のすべてのスレッドを呼び覚ます3.notifyメソッドとnotifyAllメソッドを呼び出すと、現在のスレッドは、ロックの所有権をすぐに放棄するのではなく、現在の同期コードブロックの実行が完了するまでロックを解除する必要があります.4.オブジェクトがwaitメソッドを呼び出さなかった場合、notifyメソッドを呼び出すことは影響しません.
四.例を挙げるとよりよく理解できる
これは比較的古典的な面接問題です:3スレッドでABCを印刷する問題で、Object.wait()、Object.notify()アプリケーションに対する最善の理解です.テーマの要求は以下の通りです:3つのスレッドを創立して、Aスレッドは10回Aを印刷して、Bスレッドは10回Bを印刷して、Cスレッドは10回Cを印刷して、スレッドが同時に運行することを要求して、交互に10回ABCを印刷します.この問題はObjectのwait(),notify()で簡単に解決できる.コードは次のとおりです.
public class MyThreadPrinter implements Runnable { private String name; private Object next; private Object self;
public MyThreadPrinter(String name, Object next, Object self) {
this.name = name;
this.next = next;
this.self = self;
}
@Override
public void run() {
int count = 10;
while (count > 0) {
synchronized (self) {
synchronized (next) {
System.out.print(name);
count--;
next.notify();
}
try {
self.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Main {
public static void main(String[] args) {
Object a = new Object();
Object b = new Object();
Object c = new Object();
MyThreadPrinter pa = new MyThreadPrinter("A", b, a);
MyThreadPrinter pb = new MyThreadPrinter("B", c, b);
MyThreadPrinter pc = new MyThreadPrinter("C", a, c);
new Thread(pa).start();
try {
// 。 ,abc 3 , , TheadA-->B---C, 。
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
new Thread(pb).start();
try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
new Thread(pc).start();
}
}
印刷出力:ABCABCABCABCABCABCABCABCABCABCABCABC
このコードを説明します.
我々の第一の目的は、ThreadA->ThreadB->ThreadC->ThreadAループに従って3つのスレッドを実行することである.それでは良いです:ThreadA印刷の条件:aを取得して、b ThreaddB印刷の条件:bを取得して、c ThreadC印刷の条件:cを取得して、a第1歩:初めにThreadAは先にaを取得して、それからbを取得して、印刷が終わった後に、TheadB:“b資源は私が使い終わったことを知らせて、あなたは早く目が覚めるようにしましょう!”bを先に解放し、aを再解放する第2ステップ:b優先aが解放されるので、ThreadBが先に実行(aが占有され、ThreadCが実行できない)、bを先に取得し、cを取得し、bを印刷し、cを先に解放し、bを再解放する第3ステップ:c優先bが解放されるので、ThreadCが先に実行(bが占有され、ThreadAが実行できない)、cを先に取得し、aを取得し、cを印刷し、aを先に解放する.さらにc.を解放すると、このように一歩一歩順番に実行される.
五.末尾
ここまで話しましょう.みんなに役に立つことを望んでいます.