一、wait()、notify()、notifyAll()作用
首先wait()、notify()、notifyAll()都是Object类的方法,也就是说每个对像都有wait(),notify(),notifyAll()的功能。但是必须保证调用代码对该Object是同步的,也就是说必须在作用于synchronized(obj){......}(或者synchronized修饰的函数)的内部才能够去调用obj的wait与notify/notifyAll三个方法,否则就会报错: java.lang.IllegalMonitorStateException:current thread not owner。
1. wait():等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则虽然编译可以通过,但运行时会收到一个异常:IllegalMonitorStateException。调用任意对象的 wait() 方法导致该线程阻塞,该线程不可继续执行,并且该对象上的锁被释放。
2. notify():唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候,notify是一个有序的出队列的过程(wait后的线程会进入一个FIFO的队列中,notify会按wai进入的先后顺序就行唤醒)。而短时间内多个线程竞争获得锁的顺序则是不确定的,这要靠cpu调度决定,只有在获得锁后才会接着之前wait的位置开始执行。
3. notifyAll():唤醒所有等待的线程,注意唤醒的是同一个锁对象notify之前wait的线程,对于notify之后的wait线程是没有效果的。
二、sleep的作用
sleep()方法是在线程类(Thread)中实现的,其调用者是线程对象。sleep()的作用是将当前线程暂停一定的时间,但在这期间并不释放锁。如:Thread.sleep(5000);// 睡眠5秒
三、wait()和sleep的区别
1. 两个方法来自不同的类分别是Object和Thread;
2. 最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步代码块或者同步方法,即可以进入锁内部的机会;
3. wait,notify和notifyAll只能同步代码块或同步方法里面使用,而sleep可以在何地方使用;
4. sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。
四、需要注意的是:
1. 有synchronized的地方不一定有wait,notify
2. 有wait,notify的地方必有synchronized.这是因为wait和notify不是属于线程类,而是每一个对象都具有的方法,而且,这两个方法都和对象锁有关,有锁的地方,必有synchronized。
另外,注意一点:如果要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,因为如果调用完wait,该线程就已经不是currentthread了。
3. 如果用了显式锁 Lock(java.util.concurrent.locks.ReentrantLock)就不要用 wait() 和 notify() 了,它们是两套加锁机制,不能混着用的,关于ReentrantLock的使用可见ReentrantLock使用详解。