相同点

  1. 线程状态相同,都是阻塞状态
  2. 都会进入内核态

不同点

  1. wait()方法是Object类中的方法,sleep()是Thread类中的方法
  2. wait()需要结合synchronized关键字使用,直接使用会报错,sleep()可以直接使用,Thread.sleep()。
  3. wait()方法需要notify()或者notifyAll()去唤醒,sleep()则需要打断唤醒
  4. 线程进入wait()时,会释放锁,通过notify唤醒时,需要重新进入队列排队。sleep()会持有锁进行休眠,其他竞争锁的线程无法操作。

sleep()底层原理

sleep()方法是一个native方法,其本质是使用了os函数来告诉系统,未来的多长时间内,这个线程将不参与CPU的竞争,系统内核通过内部的计时器,来计算是否到达了唤醒时间,进而将线程唤醒,继续竞争CPU。

wait()的底层原理

synchronized关键字底层实现中,有一个WaitSet,用来存放wait的线程,线程调用wait会将持有的对象头的monitor释放,并记录执行到wait()的位置,然后唤醒时,将waiting的线程继续放到entryList的等待队列中,继续排队等待获取锁

wait()、notify()注意事项

wait()、notify()必须结合synchronized关键字来使用,且操作的必须是synchronized关键字之中的对象,如果在一个synchronized对象中唤醒别的锁对象,会报错
例如:

  1. Object add = new Object();
  2. Object listen = new Object();
  3. synchronized (add){
  4. listen.notify();
  5. add.wait();
  6. }

会报错:
image.png

一句话总结:notify唤醒的是其所在锁所阻塞的线程