Java Objectのnotify()メソッド

3003 ワード

Java Objectのwait()はよく知られています notify()メソッドとスレッド間の通信が可能です.
wait()メソッド:現在のスレッドはオブジェクトロック(モニタ)の所有権を解放し、他のスレッドがこのオブジェクトのnotify()メソッドまたはnotifyAll()メソッドを呼び出す前に、現在のスレッドは待機状態にあります.
notify()メソッド:このオブジェクトロック(モニタ)で待機している単一のスレッドを起動します.複数のスレッドがこのオブジェクトで待機している場合は、いずれかのスレッドを起動することを選択します.選択は任意であり、実装に基づいて選択される.
       ここで、現在のスレッドnoitfy()を呼び出すと、待機している取得オブジェクトロックの他のスレッド(複数ある可能性がある)が直ちにwait()から返されるのではなく、notify()を呼び出す現在のスレッドがロックを解除(同期ブロックを終了)した後、wait()から戻る機会がある.この点は自分では理解できなかったので、例を挙げて深めてみましょう.
スレッド待ち:
public class WaitThread implements Runnable{
    Object lock;

    public WaitThread(Object lock){
        this.lock = lock;
    }

    public void run() {
        String threadName = Thread.currentThread().getName();
        synchronized (lock){
            System.out.println(threadName + "           ");
            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(threadName + "           ");
        }
    }
}

起動スレッド:
public class NotifyThread implements Runnable{

    Object lock;

    public NotifyThread(Object lock){
        this.lock = lock;
    }

    public void run() {
        String threadName = Thread.currentThread().getName();
        synchronized (lock){
            System.out.println(threadName + "           ");
            lock.notify();
            try {
                System.out.println(threadName + "      ");
                //    2s       
                Thread.sleep(2000);
                System.out.println(threadName + "      ");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(threadName + "           ");
            //lock.notify();       ,    
        }
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(threadName + "           ");
    }
}

注意:lock.notify()の位置とコメントの位置は、同じ効果でsynchronized同期コードブロックが実行された後にロックが解放され、他のwait()スレッドが起動する可能性があります.
メインプログラム:
public class Test {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        Thread waitThread = new Thread(new WaitThread(lock), "waitThread");
        Thread notifyThread = new Thread(new NotifyThread(lock), "notifyThread");
        waitThread.start();
        Thread.sleep(1000);
        notifyThread.start();
    }
}

出力結果:
waitThread           
notifyThread           
notifyThread      
notifyThread      
notifyThread           
waitThread           
notifyThread           

       wait()から戻るには、waitThreadスレッドがnotifyThreadスレッドが同期ブロック解放ロックを終了するまで待たなければならないことがわかります.lock.notify()はコメントが落ちた行に置かれ、出力結果は変わりません.しかし、普段の仕事では、notify()をわかりやすい位置に置くことをお勧めします.