obj.wait()让进入object监视器的线程到WaitSet等待/让持有obj的锁的线程到WaitSet中等待;
obj.notify()在object上正在WaitSet等待的线程中挑一个唤醒,是随机唤醒;
obj.notifyAll()让object上正在WaitSet等待的线程全部唤醒;

它们都是线程之间协作的手段,都属于Object类的方法。必须获得此对象的锁,才能调用这几个方法。所以wait和notify必须进入synchronized块中才可以使用,即必须拿到对象的锁才可以使用上述方法。

  1. public class TestWaitNotify {
  2. final static Object obj = new Object();
  3. public static void main(String[] args) throws InterruptedException {
  4. new Thread(()->{
  5. synchronized (obj){
  6. System.out.println("执行...");
  7. try {
  8. obj.wait();//让线程1在obj上等待下去
  9. } catch (InterruptedException e) {
  10. e.printStackTrace();
  11. }
  12. System.out.println("其它代码...");
  13. }
  14. },"t1").start();
  15. new Thread(()->{
  16. synchronized (obj){
  17. System.out.println("执行...");
  18. try {
  19. obj.wait();//让线程2在obj上等待下去
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. }
  23. System.out.println("其它代码...");
  24. }
  25. },"t2").start();
  26. //主线程两秒后执行
  27. Thread.sleep(2);
  28. System.out.println("唤醒obj上其它线程");
  29. synchronized (obj){
  30. obj.notify();
  31. }zheng
  32. }
  33. }

wait方法详解:

1、wait()

如果wait方法无参数,代表该线程会一直等待下去,直到被notify方法或者notifyAll方法唤醒才可以进入EntryList中。线程本身不会自动苏醒。源码中实际是调用了wait(0)实现一直等待。

2、wait(timeout)

单个参数的wait(timeout)方法表示线程等待毫秒级时间,如果没有notify唤醒该线程,那么时间结束后线程会自动苏醒进入EntryList队列,如果线程在timeout结束前就被notify方法唤醒,那么则不会继续等待,提前进入EntryList队列中。

wait vs sleep:

注意wait方法和sleep方法的区别,sleep方法是线程想睡就睡,如果线程持有锁调用sleep方法后并不会释放锁。wait方法是只有当线程持有锁后才可以调用wait方法,而且调用wait方法后会释放锁。