javaのスレッド待ちとお知らせの実現

3982 ワード

javaのスレッド待ちとお知らせの実現
前言:
待つ/知らせについて、覚えておくべきポイントは:
同期環境内からwait()、notify()、notifyAll()方法を呼び出す必要があります。スレッドはそのオブジェクトのロックがない限り、オブジェクト上で待つ方法や通知方法を呼び出すことができません。
wait()、notify()、notifyAll()はすべてObjectの実例的な方法です。各オブジェクトがロックを持っているのと同様に、各オブジェクトはスレッドリストを持っていてもよく、信号(通知)を待っています。スレッドは、オブジェクト上のwait()方法を実行することにより、この待ちリストを取得する。その時から、オブジェクトのnotifyメソッドを呼び出すまで、他のコマンドは実行されなくなります。複数のスレッドが同一のオブジェクト上で待機している場合は、一つのスレッドのみを選択して実行します。スレッドが待機していない場合は、特別な操作は行われません。
 サンプルコード:

package threadwait;

public class ThreadA extends Thread{

  public int num = 0;

  public void run(){

    synchronized (this){//          ,this      

      for(int i = 0 ; i < 3 ; ++i)

       this.num+=i;

      notifyAll();//                   ,       TestNotify       

    }

  }

  public int getNum(){

    return this.num;

  }

}


package threadwait;

 

public class TestNotify{

  public static void main(String args[]){

    ThreadA threada = new ThreadA();

    threada.start();//threada        ,         

    synchronized(threada){

      try{

       threada.wait();//     threada           

       //         threada          wait,             wait,  wait      

      }catch(InterruptedException e){

       e.printStackTrace();

      }

    }

    System.out.println(threada.getNum());

  }

}

同期はclassレベルであっても良いし、synchronized(A.class)であっても良いし、対象レベルのsynchronized(this)であっても良いし、静的同期方法はclassレベルであり、非静的同期方法はクラス対象レベルであり、一つのオブジェクトは一つのロックしかないので、wait操作ができます。後にこのロックを解除します。
さらなるインスタンスコードは以下の通りです。

package threadwait;

 

public class ThreadA extends Thread{

  public int num = 0;

  public void run(){

    synchronized (this){//          ,this      

      for(int i = 0 ; i < 3 ; ++i)

       this.num+=i;

      try{

       Thread.sleep(500);//  ThreadB                       notifyall   

       //         ,    notifyall          notifyall,               

       //           ,              。

       //     

      }catch(InterruptedException e){

       e.printStackTrace();

      }

      notifyAll();//                   ,       TestNotify       

    }

//   notifyAll();

  }

  public int getNum(){

    return this.num;

  }

}


package threadwait;

 

public class ThreadB extends Thread{

  private ThreadA threada;

  public ThreadB(ThreadA ta){

    this.threada = ta;

  }

  public void run(){

    System.out.println(Thread.currentThread().getName()+" is waitting.");

    synchronized(threada){

      try{

       threada.wait();

      }catch(InterruptedException e){

       e.printStackTrace();

      }

      System.out.println(Thread.currentThread().getName()+" "+this.threada.getNum());

    }

   

  }

}


package threadwait;

 

public class TestNotify{

  public static void main(String args[]){

    ThreadA threada = new ThreadA();

    new ThreadB(threada).start();

    new ThreadB(threada).start();

    new ThreadB(threada).start();

    threada.start();

  }

}

疑問があれば、メッセージをお願いします。あるいは、当駅のコミュニティで交流して討論してください。ありがとうございます。