Object类中的wait()方法和notify()方法

【Object类中的wait()方法和notify()方法】

wait():
	public final void wait(long timeout) throws InterruptedException
	参数:等待的时间,可选,不填则默认为0。
	说明:
		1>使线程主动释放对象锁,并进入等待状态,直到它被其他线程通过notify()或notifyAll唤醒或者超过指定的等待时间。
		2>在调用wait方法前,线程必须获得该对象的对象锁,即:只能在同步方法或同步代码块中调用wait方法,如果当前线程不是锁的持有者,将抛出一个IllegalMonitorStateException异常(是RuntimeException的子类,故不需要捕获)。
		3>wait方法执行完成后,该线程立即释放持有的对象锁(注:不是等到退出synchronized代码块后才释放)。
		4>this method should always be used in a loop:
		
			synchronized (obj) {
				// 不满足条件时等待。	
				while (condition does not hold) {	
					obj.wait();						// 注:一般会有其它的线程当条件满足后调用notify方法
				}		
				// 满足条件时执行execute方法。
				execute();					 		// 注:使用while循环保证了这行代码始终是在满足条件下被执行的!	
			}
			
			举例:
				阶段1)A线程执行该代码块时,发现不满足条件condition,则A线程进入等待状态,并释放对象锁,
				阶段2)B线程执行某些代码后,满足了条件condition,然后调用notify()方法并释放了对象锁,
				阶段3)如果此时C线程获得了该对象锁,并执行了某些代码导致又不满足条件condition了,当C线程释放该对象锁后,
				阶段4)A线程才获得了该对象锁,并执行wait()方法后面的代码。如果不使用while循环,而是使用if语句来判断(如下),则会导致execute()方法在不满足条件的情况下被执行了!
					synchronized (obj) {
						if (condition does not hold) {	
							obj.wait();
						}
						execute();
					}
			解析:
				执行execute方法的情况:
					1)执行代码块时,条件已满足,则不会调用wait方法,直接执行execute方法。
					2)执行代码块时,条件不满足,则调用wait方法,等到被唤醒后(注:被唤醒后条件可能发生变化),再去执行execute方法。
				使用while循环:保证了在调用wait方法前(阶段1)和在被唤醒后(阶段4)都去检查条件是否满足,如果满足则执行excute方法,如果不满足则继续等待。
				使用if语句:只保证了在调用wait方法前(阶段1)去检查条件是否满足,并没有在线程被唤醒后去检查是否满足条件。如果发生了阶段3的情况,则execute方法将在不满足条件的情况下执行了。


notify():
	public final void notify()
	说明:
		1>随机选择一个在该对象上调用wait方法的线程,赋予其对象锁,解除其阻塞状态。
		2>在执行notify()方法后,当前线程不会马上释放该对象锁,要等到执行notify()方法的线程退出synchronized方法或synchronized代码块后,当前线程才会释放锁,此时wait状态的线程才可以获取该对象锁,并继续执行synchronized代码块中wait()方法后面的代码。
	
	
notifyAll():
	public final void notifyAll()
	说明:唤醒在该对象上调用wait方法等待的所有线程。
	

说明:wait()、notify()、notifyAll()这三个方法:
	1)在调用方法前,线程必须获得该对象的对象锁,如果当前线程不是锁的持有者,方法将抛出一个IllegalMonitorStateException异常(是RuntimeException的子类,故不需要捕获)。
	2)只能在非静态同步方法或非静态同步代码块内调用,而且必须由锁对象来调用方法:
		1>这3个方法都是非静态方法,且这3个方法必须由锁对象调用,所以我们不能在静态同步方法和静态代码块中调用(静态同步方法的锁是类的Class锁)。
		2>synchronized修饰的非静态方法:因为this就是锁对象,所以可以在同步方法中调用这三个方法(可以将this省略)。
		3>synchronized修饰的非静态同步代码块:必须使用锁对象来调用这三个方法。
	3)由于wait,notify和notifyAll都是锁级别的操作,而锁属于对象,故把他们定义在Object类中,而不是定义在Thread类中。

猜你喜欢

转载自my.oschina.net/u/1399755/blog/1811431