【Object类中的wait()方法和notify()方法】oop
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类中。