转载请注明出处:http://blog.csdn.net/ns_code/article/details/17225469

wait()方法:public final void wait()  throws InterruptedException,IllegalMonitorStateException

  wait()方法使得当前线程必须要等待,等到另外一个线程调用notify()或者notifyAll()方法。

  当前的线程必须拥有当前对象的monitor,也即lock,就是锁。

  线程调用wait()方法,释放它对锁的拥有权,然后等待另外的线程来通知它(通知的方式是notify()或者notifyAll()方法),这样它才能重新获得锁的拥有权和恢复执行。

  要确保调用wait()方法的时候拥有锁,即,wait()方法的调用必须放在synchronized方法或synchronized块中。

  一个小比较:

  当线程调用了wait()方法时,它会释放掉对象的锁。

  另一个会导致线程暂停的方法:Thread.sleep(),它会导致线程睡眠指定的毫秒数,但线程在睡眠的过程中是不会释放掉对象的锁的。

notify()方法public final native void notify() throws IllegalMonitorStateException

  notify()方法会唤醒一个等待当前对象的锁的线程。

  如果多个线程在等待,它们中的一个将会选择被唤醒。这种选择是随意的,和具体实现有关。(线程等待一个对象的锁是由于调用了wait方法中的一个)。

  被唤醒的线程是不能被执行的,需要等到当前线程放弃这个对象的锁。

  被唤醒的线程将和其他线程以通常的方式进行竞争,来获得对象的锁。也就是说,被唤醒的线程并没有什么优先权,也没有什么劣势,对象的下一个线程还是需要通过一般性的竞争。

  notify()方法应该是被拥有对象的锁的线程所调用。

  (This method should only be called by a thread that is the owner of this object's monitor.)

  换句话说,和wait()方法一样,notify方法调用必须放在synchronized方法或synchronized块中。

  wait()和notify()方法要求在调用时线程已经获得了对象的锁,因此对这两个方法的调用需要放在synchronized方法或synchronized块中。

  一个线程变为一个对象的锁的拥有者是通过下列三种方法:

  1.执行这个对象的synchronized实例方法。

  2.执行这个对象的synchronized语句块。这个语句块锁的是这个对象。

  3.对于Class类的对象,执行那个类的synchronized、static方法。

notifyAll()

public final native void notifyAll() throws IllegalMonitorStateException

该方法与notify()方法的工作方式相同,重要的一点差异是:

notifyAll使所有原来在该对象上wait的线程统统退出wait的状态(即全部被唤醒,不再等待notify或notifyAll,但由于此时还没有获取到该对象锁,因此还不能继续往下执行),变成等待获取该对象上的锁,一旦该对象锁被释放(notifyAll线程退出调用了notifyAll的synchronized代码块的时候),他们就会去竞争。如果其中一个线程获得了该对象锁,它就会继续往下执行,在它退出synchronized代码块,释放锁后,其他的已经被唤醒的线程将会继续竞争获取该锁,一直进行下去,直到所有被唤醒的线程都执行完毕。

深入理解:

   如果线程调用了对象的wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。

   当有线程调用了对象的notifyAll()方法(唤醒所有wait线程)或notify()方法(只随机唤醒一个wait线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。

   优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了synchronized代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

实例:https://git.oschina.net/wenjieyatou/threadTest

最新文章

  1. 【阿里云产品公测】阿里云ECS服务器,PTS网站性能
  2. Android关于buildToolVersion与CompileSdkVersion的区别
  3. 每天2个android小例子----简单计算器源代码
  4. Visual Studio 2015和.Net 2015 预览版在线安装和ISO镜像安装光盘下载
  5. oracle flashback
  6. 《玩转shutdown》-linux命令五分钟系列之十三
  7. QTP的DataTable操作整理(注---不知转载多少遍)
  8. Sqlserver统计语句
  9. 请教下关于CKEditor富文本编辑框设置字体颜色的问题
  10. WPF: ShowDialog() 切换到其他应用窗口后,再切换回来无法让子窗口总在最上方
  11. LABjs、RequireJS、SeaJS 哪个最好用?为什么?- 玉伯的回答
  12. 201671010142 2017-2 《java第九章学习感悟》
  13. 函数append()和html()的区别
  14. 如何重置mysql中的root密码
  15. [LeetCode] Wiggle Sort II 摆动排序之二
  16. 收藏 —— KVM网络虚拟化
  17. 2013长春网赛1010 hdu 4768 Flyer
  18. java后台list集合传值到前台,再取值的几种方法
  19. Oracle 小函数的使用
  20. linux内核分析 第六周读书笔记

热门文章

  1. cf723b Text Document Analysis
  2. linuxmint 17安装scim输入法
  3. 【荐】PHP Session和Cookie,Session阻塞,Session垃圾回收,Redis共享Session,不推荐Memcached保存Session
  4. redis中的key设置过期时间
  5. 逻辑思维面试题-java后端面试-遁地龙卷风
  6. and or bool and a or b 原理解释
  7. Linq查询表达式
  8. socket阻塞与非阻塞,同步与异步、I/O模型,select与poll、epoll比较
  9. 使用curl进行https请求
  10. 使用原生ajax处理json字符串