notify()和notifyAll()
?
关于方法notify()和notifyAll()哪些说法是正确的???
请选出两个正确答案?
A)类Thread的一个实例有一个名为notify()的方法,该方法可以被调用。?
B)一个到方法notify()的调用将唤醒当前拥有对象锁定的线程。?
C)方法notify()是同步的。?
D)方法notifyAll()在类Thread中被定义的。?
E)当有超过一个线程在等待获得一个对象的锁定时,那么就无法确定notify()方法将通知哪个线程。??????
A是对的,因为万物皆是类,Thread对象也是Object对象,所以也拥有notify方法,这种说法看似乎很怪,想想线程本身拥有这两个方法,未必有用,但在线程池中,线程做为一个对象进行存取控制的时候,就有用了。
B是错的。B的不是特别严谨,notify唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。另外还一个严重的说法错误,如果现有线程不是对象锁定的主人,那么将抛出一个IllegalMonitorStateException错误。
C是错的。notify方法在Object类中定义,但调用notify必须在同步代码块中调用。此方法不同步,但是如果现有线程不是对象锁定的主人,那么将抛出一个IllegalMonitorStateException,这两者理解上千万不要混淆在一起。在API中,方法的原型说明:?????
public final void notify()
wait
?方法,在对象的监视器上等待。D是错的。明显是错的。
E是对的。对象在wait时会释放synchonrized的锁,被唤醒后会重新获取。notify() 是随机选择其中一个唤醒,其它仍然在wait。notifyAll() 是全部都唤醒,全部都尝试重获锁,当然只有其中一个会得到并继续执行,其它得不到锁的继续等待,但这时是等待锁,而不是等待notify。
?
?
notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法。两者的最大区别在于:notifyAll使所有原来在该对象上等待被notify的线程统统退出wait的状态,变成等待该对象上的锁,一旦该对象被解锁,它们就会去竞争。notify则文明得多他只是选择一个wait状态线程进行通知,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们,当第一个线程运行完毕以后释放对象上的锁此时如果该对象没有再次使用notify语句,则即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象发出一个notify或notifyAll,它们等待的是被notify或notifyAll,而不是锁。import java.util.*;class Widget{}class WidgetMaker extends Thread{ List finishedWidgets=new ArrayList(); public void run(){ try{ while(true){ Thread.sleep(5000);//act busy Widget w=new Widget(); //也就是说需要5秒钟才能新产生一个Widget,这决定了一定要用notify而不是notifyAll //因为上面两行代码不是同步的,如果用notifyAll则所有线程都企图冲出wait状态 //第一个线程得到了锁,并取走了Widget(这个过程的时间小于5秒,新的Widget还没有生成) //并且解开了锁,然后第二个线程获得锁(因为用了notifyAll其他线程不再等待notify语句 //,而是等待finishedWidgets上的锁,一旦锁放开了,他们就会竞争运行),运行 //finishedWidgets.remove(0),但是由于finishedWidgets现在还是空的, //于是产生异常 //***********这就是为什么下面的那一句不能用notifyAll而是要用notify? synchronized(finishedWidgets){ finishedWidgets.add(w); finishedWidgets.notify(); //这里只能是notify而不能是notifyAll } } } catch(InterruptedException e){} }? public Widget waitForWidget(){ synchronized(finishedWidgets){ if(finishedWidgets.size()==0){ try{ finishedWidgets.wait(); } catch(InterruptedException e) {} } return finishedWidgets.remove(0); } }}public class WidgetUser extends Thread{ private WidgetMaker maker; public WidgetUser(String name,WidgetMaker maker){ super(name); this.maker=maker; } public void run(){ Widget w=maker.waitForWidget(); System.out.println(getName()+"got a widget"); }? public static void main(String[] args) { WidgetMaker maker=new WidgetMaker(); maker.start(); new WidgetUser("Lenny",maker).start(); new WidgetUser("Moe",maker).start(); new WidgetUser("Curly",maker).start(); }}