Java中Objectのwait()notify()notifyAll()方法は使用します。


Java中Objectのwait()notify()notifyAll()方法は使用します。
はじめに
同時プログラミングについては、Thread以外にもObjectオブジェクトのwatiとnotifyオブジェクトに対して、その使い方を深く知るべきです。知識点は少ないですが。
二、スレッド安全基本知識
まずは以下の基本を覚えて、覚えておいてもいいです。
同じ時間に、一つのスレッドにしか呼び出されないwait()とnotify()を持つ前に必ず持っていなければなりません。
三、wait()とnotify()は理解します。
3.1 wait()とnotify()方法概要
wait()とnotify()はいずれもObjectの方法であり、どのObjectも資源(またはリソースの代表)であると考えられ、複数のスレッドが一つのリソースを操作する場合、スレッドがまだ準備されていないことを発見すれば、このリソース上で待つことができます。すなわち、このリソースを呼び出すwait()方法です。他のスレッドがある場合、いくつかの処理を経てこのリソースが利用できると思います。このリソースのnotify()メソッドを呼び出して、スレッドを待つと教えてくれます。このリソースは使えます。
もちろんwait()とnotify()の方法を使わなくてもいいです。while()のデッドサイクルで判断できます。下記のような疑似コードです。

class Resource{
  static boolean canUse=false;
}

while(!Resource.canUse){
  //     ,        
}

//        ,      ,    
これはいいですが、CPUリソースを特に消費するので、wait()とnotify()の方法を利用することをお勧めします。
3.2 wait()とnotify()の価値
実は単語の意味から分かります。waitは待っています。この資源が準備されていないと説明します。待ちます。またこのwaitがあります。あなたを待つしかないという意味です。時間が経っても大丈夫です。notify()を呼ぶスレッドは必ず資源を処理して、処理が終わったらお知らせします。ですから、生産者と消費者モードでよく使われています。どのような資源が到来するかに関する情景もこの二つの方法に適しています。
3.3なぜwait()とnotify()はsynchronizedと一緒に使わなければなりませんか?
synchronized同期ブロックにwait()とnotify()または呼び出し方法の対象がsynchronizedではない同期ロックは異常です。

java.lang.IllegalMonitorStateException
なぜこの対象の鍵を持たないと相手のwait()とnotify()を呼び出すことができないのかと疑問に思う人が多いです。まず次のコードを見ます。

public class WaitTest{
  //       ,   Object
  final NoObjct resource=new NoObjct();
  public static void main(String[] args) throws Exception{
    WaitTest d=new WaitTest();
    d.test();
  }

  public void test() throws Exception{
    Runnable r=new Runnable(){
      public void run(){
        //         wait  ,       synchronized
        resource.noWait();
        System.out.println('     ,  ');
      }
    };
    Thread t=new Thread(r);
    t.start();
    Thread.sleep(2000);
    System.out.println('           ');
    //         notify  ,       synchronized
    resource.noNotify();
  }
}

//  wait() notify() final  ,    ,      Object  
class NoObjct{
  //   wait  
  public void noWait(){
    //        synchronized  wait    
    synchronized(this){
      try{
        this.wait();
      }catch(InterruptedException e){
        e.printStackTrace();
      }
    }
  }
  //   notify  
  public void noNotify(){
    //        synchronized  notify    
    synchronized(this){
      this.notify();
    }
  }
}
これは簡単なwait()とnotify()の例です。waitは待ちます。シミュレーションのObjectを無視するとコードが簡潔になります。そうでないと毎回synchronizedを使います。以下のコードです。

public class WaitTest{
  //       ,   Object
  final Object resource=new Object();

  public static void main(String[] args) throws Exception{
    WaitTest d=new WaitTest();
    d.test();
  }

  public void test() throws Exception{
    Runnable r=new Runnable(){
      public void run(){
        //     synchronized
        try{
          synchronized(resource){
            resource.wait();
          }
        }catch(InterruptedException e){
          e.printStackTrace();
        }
        System.out.println('     ,  ');
      }
    };
    Thread t=new Thread(r);
    t.start();

    Thread.sleep(2000);
    System.out.println('           ');
    //     synchronized
    synchronized(resource){
      resource.notify();
    }
  }
}
だから、wait()とnotify()はsynchronizedと一緒に意味がないと思います。結局、synchronizedはコードを同期させるために使われています。スレッド間の起動とは関係がないと思います。しかし、このように規定されている以上は、必ず守らなければならない。すなわち、synchronizedでwaitとnotifyを使用しなければならず、また呼び出し方法の対象は同期対象でなければならない。
四、いつwait()とnotify()を使いますか?
この二つの方法の中の一つの価値は生産者と消費者モードで使うことです。しかし、それらを使用して構築された生産者と消費者モデルは非常に低級で複雑であり、BlockingQueインターフェースの実装クラスを使用して構築されている。例えば、ArayBlocking Queを使うことができます。スレッドの安全を保証し、ブロック効果を実現できます。
これ以外はスレッド間の休止と目覚ましだけです。
     読んでくれてありがとうございます。みなさんのご協力をお願いします。ありがとうございます。