线程通信涉及到的三个方法

wait() 方法:

  • 在当前线程中调用方法: 对象名.wait()
  • 使当前线程进入等待(某对象)状态 ,直到另一线程对该对象发出 notify (或notifyAll) 为止。
  • 调用方法的必要条件:当前线程必须具有对该对象的监控权(加锁)
  • 调用此方法后,当前线程将释放对象监控权 ,然后进入等待
  • 在当前线程被notify后,要重新获得监控权,然后从断点处继续代码的执行。

    notify()/notifyAll()

  • 在当前线程中调用方法:对象名.notify()

  • 功能: notify()唤醒正在排队等待同步资源的线程中优先级最高者结束等待 , notifyAll ()唤醒正在排队等待资源的所有线程结束等待.
  • 调用方法的必要条件:当前线程必须具有对该对象的监控权(加锁)

注:
这三个方法只有在synchronized方法或synchronized代码块中才能使用,否则会报 java.lang.IllegalMonitorStateException异常。
因为这三个方法必须同步监视器对象调用,而任意对象都可以作为synchronized的同步锁, 因此这三个方法只能在Object类中声明


小结有关锁的操作

  • 释放锁的操作

当前线程的同步方法、同步代码块执行结束。
当前线程在同步代码块、同步方法中遇到break、return终止了该代码块、 该方法的继续执行。
当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致异常结束。
当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线程暂停,并释放锁。

  • 不会释放锁的操作

线程执行同步代码块或同步方法时,程序调用Thread.sleep()、 Thread.yield()方法暂停当前线程的执行,此时不会释放锁
线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁(同步监视器)。
应尽量避免使用suspend()和resume()来控制线程


面试题:sleep() 和 wait()的异同?

相同点:一旦执行方法,都可以使得当前的线程进入阻塞状态。
不同点:
1)两个方法声明的位置不同:Thread类中声明sleep() , Object类中声明wait()
2)调用的要求不同:sleep()可以在任何需要的场景下调用。 wait()必须使用在同步代码块或同步方法中
3)关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁。