Object类中的wait()等待方法,notify()唤醒方法
两个方法的签名如下:
* public final void wait() throws InterruptedException
* public final native void notify();
* wait()方法:在线程thread1中调用了obj.wait()方法,线程thread1就会停止继续执行转为等待状态,线程thread1会一直等到其它线程调用obj.notify() 方法后等待结束
wait()和notify()的工作过程:
*如果一个线程调用了obj.wait()方法,那么它就会进入Object对象的等待队列,这个等待队列中可能会有n个线程,因为系统运行多个线程同时等待某一个对象
* 当obj.notify()方法被调用时,系统会从Object对象的等待队列中随机选择一个线程将其唤醒,这个选择是不公平的,并不是先等待的线程优先被选择,这个选择是随机的
Object.wait()方法和Object.notify()方法的工作细节
*wait()不能随便使用,它必须在synchronized语句中使用,无论是wait()还是notify()使用之前要获取对应的的锁对象,
* 一个线程在正确的执行wait()方法之前,要获取对应的锁,在执行wait()方法之后要释放掉锁,这样的目的是使在object等待队列中的其它线程不会因为某一个线程休眠而无法正常运行
* 一个线程在执行notify()方法之前,要先获取对应的锁(wait()方法执行结束后已经释放了锁),notify()方法执行后,会随机唤起一个线程,这个线程被唤醒后不会立即执行,而是先去取对应的锁,只有获取到对应的锁之后才会去执行后续的代码
Object类中的notifyAll()
签名如下:
* public final native void notifyAll();
* notifyAll()方法与notify()用法和原理相同,只不过notifyAll()方法会将object对象等待队列中的所有线程唤醒,而不是随机选择一个
示例理解代码
public class SimpleWaitNotify {
private static final Logger logger = LoggerFactory.getLogger(SimpleWaitNotify.class);
private static final Object obj = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (obj) {
logger.info("{}:thread1 wait fornt", System.currentTimeMillis());
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("{}:thread1 wait after", System.currentTimeMillis());
}
});
Thread thread2 = new Thread(() -> {
synchronized (obj) {
logger.info("{}:thread2 notify fornt", System.currentTimeMillis());
obj.notify();
logger.info("{}:thread2 notify after", System.currentTimeMillis());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread1.start();
thread2.start();
}
}
执行结果
Object.wait()和Thread.sleep()区别:
* 1.wait()是Object中的方法,sleep()是Thread中的方法
* 2.两者都可传入时间,让线程等待若干时间,wait()可以被notify()唤醒
* 3.wait()会释放锁,sleep()不会释放锁