sleepおよびスレッドのコラボレーションjava wait、notify、notifyAll

5898 ワード

sleep()は現在のスレッドを停滞状態(現在のスレッドをブロック)にし、CUPの使用を譲り、現在のスレッドがそのプロセスで得られたCPUリソースを独自に占領しないようにし、他のスレッドに実行する機会を一定時間残し、オブジェクトのマシンロックを変更することができないため、1つのSynchronizedブロックでSleep()を呼び出す方法は、スレッドはスリープしているが、ただし、オブジェクトはロックが解放されたままであり、他のスレッドはそのオブジェクトのロックを取得する(寝ていてもオブジェクトロックを保持する).sleep()スリープ時間が満了すると、スレッドはすぐに実行されるとは限らない.これは、他のスレッドが実行中であり、このスレッドがより高い優先度を持たない限り、実行を放棄するようにスケジューリングされていないためである.
       Javaでのスレッド間のコラボレーションは、Objectのwait()メソッドとnotify()メソッドによって実現され、1つのスレッドがwait()メソッドに実行されると、オブジェクトに関連する待機プールに入り、オブジェクトのマシンロック(一時的にオブジェクトロックを失い、wait(long timeout)がタイムアウトした後にオブジェクトロックを返す必要がある)を失う(解放する).他のスレッドにアクセスできます.
       wait()とsleep()は、interrupt()メソッドによってスレッドの一時停止状態を遮断し、InterruptedExceptionをすぐに放出することができます(ただし、このメソッドは推奨されません).
wait()とsleep()の違い:1)sleep()メソッドはThreadクラスのメソッドであり,wait()メソッドはObjectのメソッドである.2)sleep()メソッドはオブジェクトのロックを解放しないが,wait()メソッドの呼び出しはオブジェクトのロックを解放し,notify()またはnotifyAll()メソッドによりオブジェクトのロックを再び得ることができる.次に、wait()メソッドについて簡単に説明します.1)wait()メソッドはsleep()メソッドと同様に、ミリ秒数を受け入れることができ、現在指定された時間が過ぎた後、オブジェクトは再びロックを取得します.2)wait()、notify()およびnotifyAll()は、同期制御メソッドまたは同期制御ブロックで呼び出さなければなりません.そうしないと、IllegalMonitorStateException例外が放出されます.3)wait()メソッドを使用する場合は、while文にネストし、スレッドの予期せぬ起動を防止する必要があります(notifyAllメソッド).   
     コードブロックは次のとおりです.
  synchronized(obj1)             //1.        
  {   
          try   {   
          ...   
          obj1.wait();                 //2.         
          }catch   (InterruptedException   exp)   {}   
  }   

       1.現在の同期オブジェクト(monitor)はobj 1、obj 1のいずれかの例である、同期方法の場合、同期オブジェクトはthisである.同期ブロックに入ると、obj 1はロック状態となり、ロック状態はobj 1自体に影響を及ぼさず、他のスレッドが同一コードに実行する場合、ロックが得られないためBlock状態となり、一旦ロックが解除すると、blockのスレッドによって自動的に実行が継続する.    2.obj 1.wait()を呼び出すには、スレッドを待機状態にすることと、obj 1をロック解除することと、ブロックされたスレッドによってロックが得られることの2つの役割がある.スレッド1が待機を終了するには、他のスレッドによって明示的にobj 1.notify()またはnotifyAll()を呼び出す方法が必要である.     のように   
  synchronized(obj1)   
  {   
          ...   
          obj1.notify();         //3.    wait           
          ...   
  }  

 他のスレッドがこのときまで実行するスレッド1がwait状態であればwait状態は解除され、解除後、スレッド1がロックされていれば実行を継続する、複数のスレッドがobj 1のwait状態であればnotifyはランダムに1つのスレッドを選択してアクティブ化する、notifyAllは同時にすべてのwait状態を解除する. 
同期ブロックのエントリポイントがブロックされている場合、他のスレッドがnotify()を呼び出す必要がなく、調整しても効果がなく、同期ブロックは自動的にロックを得ることができます.   waitがブロックされている場合はnotfiy()でアクティブ化する必要があります.この2つの方法は組み合わせて使用します. 
次に具体例を用いて
 
package com.test;

import java.text.SimpleDateFormat;
import java.util.Date;

public class threadTest {
	public  void waitFunction(){
		synchronized(this)             //1.           
		{      
		        try{ 
		        	System.out.println( "  waitFunction" );
		        	this.wait();                 //2.          
		        	System.out.println( "  waitFunction" );
		        }catch   (InterruptedException   exp){
		        	
		        	
		        }      
		}    
	}
	public  void notifyFunction(){
		synchronized(this)             //1.           
		{      
			    System.out.println( "  notifyFunction" );
		        this.notify();                 //2.    
		        System.out.println( "  notifyFunction" );
		}    
	}
	
	public  void sleepFunction(){
		synchronized(this)             //1.           
		{      
		        try{ 
		        	System.out.println( "  sleepFunction" );
		        	Thread.sleep( 9000 );                 //2.          
		        	System.out.println( "  sleepFunction" );
		        }catch   (InterruptedException   exp){
		        	
		        	
		        }      
		}    
	}
	public static void main(String args[]){
		final threadTest tt= new threadTest();
		final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//      
		new Thread(){ public void run(){
			
			System.out.println( "  1 sleepFunction()"+df.format(new Date()));
			tt.sleepFunction();
			 
		 }  }.start(
		);
		
		new Thread(){ public void run(){
			System.out.println( "  2 waitFunction()"+df.format(new Date()) );
			tt.waitFunction();
			 
		 }  }.start(
		);
		 
		 try {
			Thread.sleep(20000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
			new Thread(){ public void run(){
				
				System.out.println( "  3 notifyFunction()"+df.format(new Date()) );
				
				tt.notifyFunction();
				 
			 }  }.start(
			);
		
	}
   
}

 
  1 sleepFunction()2013-03-28 15:24:45
  2 waitFunction()2013-03-28 15:24:45
  sleepFunction
  sleepFunction
  waitFunction
  3 notifyFunction()2013-03-28 15:25:05
  notifyFunction
  notifyFunction
  waitFunction

結果分析:
     (1):スレッド1実行時のsleepFunction.sleepはオブジェクトロックを維持するため、他のスレッドは他の同期ブロックにアクセスできません.
     (2):スレッド2で実行されるwaitFunctionは、waitFunctionが実行されるとsleepがオブジェクトロックを維持するため、sleepがオブジェクトロック「つまりスリープ時間が過ぎて関連コードが実行される」まで同期ブロックを実行できず、waitFunction同期ブロックに入るため、前の5ステップの出力
  1 sleepFunction()2013-03-28 15:24:45
  2 waitFunction()2013-03-28 15:24:45
  sleepFunction
  sleepFunction
  waitFunction

   (3):スレッド2実行 waitメソッドの後、ロックリソースを解放し、待機状態に入り、スレッド3が実行されると、スレッド2がロックリソースを解放しているため、同期ブロックに入りnotifyメソッドを実行し、wait状態スレッドを起動し、waitスレッドに継続的な作業を完了させることができる.これはなぜ後4ステップ出力が
  3 notifyFunction()2013-03-28 15:25:05
  notifyFunction
  notifyFunction
  waitFunction