在多线程的情况下。因为多个线程与存储空间共享相同的过程,同时带来的便利。它也带来了访问冲突这个严重的问题。

Java语言提供了一种特殊的机制来解决这类冲突,避免同一数据对象由多个线程在同一时间访问。

wait与notify是java同步机制中重要的组成部分。结合与synchronizedkeyword使用。能够建立非常多优秀的同步模型。

  synchronized(this){ }等价于publicsynchronized void method(){.....}

   同步分为类级别和对象级别,分别相应着类锁和对象锁。类锁是每一个类仅仅有一个,假设static的方法被synchronizedkeyword修饰。则在这种方法被运行前必须获得类锁;对象锁类同。

   首先,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于synchronized(obj){......}的内部才可以去调用obj的wait与notify/notifyAll三个方法,否则就会报错:

  java.lang.IllegalMonitorStateException:current thread not owner

  在调用wait的时候。线程自己主动释放其占有的对象锁,同一时候不会去申请对象锁。当线程被唤醒的时候。它才再次获得了去获得对象锁的权利。

  所以,notify与notifyAll没有太多的差别。仅仅是notify仅唤醒一个线程并同意它去获得锁,notifyAll是唤醒全部等待这个对象的线程并同意它们去获得对象锁,仅仅要是在synchronied块中的代码。没有对象锁是寸步难行的。事实上唤醒一个线程就是又一次同意这个线程去获得对象锁并向下执行。

notifyAll,尽管是对每一个wait的对象都调用一次notify,可是这个还是有顺序的。每一个对象都保存这一个等待对象链,调用的顺序就是这个链的顺序。事实上启动等待对象链中各个线程的也是一个线程。在详细应用的时候,须要注意一下。

wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每一个对像都有wait(),notify(),notifyAll()的功能。由于都个对像都有锁,锁是每一个对像的基础,当然操作锁的方法也是最基础了。

wait():

等待对象的同步锁,须要获得该对象的同步锁才干够调用这种方法,否则编译能够通过,但执行时会收到一个异常:IllegalMonitorStateException。

调用随意对象的 wait() 方法导致该线程堵塞。该线程不可继续运行,而且该对象上的锁被释放。

notify():

唤醒在等待该对象同步锁的线程(仅仅唤醒一个,假设有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程。而是由JVM确定唤醒哪个线程。并且不是按优先级。

调用随意对象的notify()方法则导致因调用该对象的 wait()方法而堵塞的线程中随机选择的一个解除堵塞(但要等到获得锁后才真正可运行)。

notifyAll():

唤醒全部等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。

通常,多线程之间须要协调工作:假设条件不满足。则等待;当条件满足时。等待该条件的线程将被唤醒。

在Java中。这个机制的实现依赖于wait/notify。

等待机制与锁机制是密切关联的。

比如:

  synchronized(obj) {

  while(!condition) {

  obj.wait();

  }

  obj.doSomething();

  }

  

  当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。

  在还有一线程B中。假设B更改了某些条件,使得线程A的condition条件满足了,就能够唤醒线程A :

  

  synchronized(obj) {

  condition = true;

  obj.notify();

  }

  

  须要注意的概念是:

  

  # 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj){...} 代码段内。

  

  # 调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj){...} 代码段内唤醒A。

  

  # 当obj.wait()方法返回后。线程A须要再次获得obj锁。才干继续运行。

  

  #假设A1,A2,A3都在obj.wait(),则B调用obj.notify()仅仅能唤醒A1,A2,A3中的一个(详细哪一个由JVM决定)。

  

  #obj.notifyAll()则能所有唤醒A1,A2,A3,可是要继续运行obj.wait()的下一条语句,必须获得obj锁。因此。A1,A2,A3仅仅有一个有机会获得锁继续运行,比如A1,其余的须要等待A1释放obj锁之后才干继续运行。

  

  # 当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此。A1,A2,A3虽被唤醒,可是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续运行。

  

谈一下synchronized和wait()、notify()等的关系:

1.有synchronized的地方不一定有wait,notify

2.有wait,notify的地方必有synchronized.这是由于wait和notify不是属于线程类,相反,每个对象具有一个方法。和。这两种方法以及相关的对象锁。锁定的地方,必须synchronized。

其他,注意:应该承担notify和wait方法一起用的话。你必须调用notify后打电话wait,因为假定调用完wait,线程是不currentthread该。

Java多线程的wait(),notify(),notifyAll()的更多相关文章

  1. Java多线程:wait(),notify(),notifyAll()

    1. wait(),notify(),notifyAll() 2. wait() 2.1. wait() 2.2. wait(long timeout) 2.3. wait(long timeout, ...

  2. java 多线程(wait/notify/notifyall)

    package com.example; public class App { /* wait\notify\notifyAll 都属于object的内置方法 * wait: 持有该对象的线程把该对象 ...

  3. java多线程中wait/notify/sleep/join/yield方法以及多线程的六种状态

    刚开始学线程的时候也是被这几个方法搞的云里雾里的,尤其是一开始看的毕老师的视频,老师一直在强调执行权和执行资格,看的有点懵逼,当然不是说毕老师讲的不好,就是自己有点没听明白,后来复习看了一些其他的博客 ...

  4. java中的wait(),notify(),notifyAll(),synchronized方法

    wait(),notify(),notifyAll()三个方法不是Thread的方法,而是Object的方法.意味着所有对象都有这三个方法,因为每个对象都有锁,所以自然也都有操作锁的方法了.这三个方法 ...

  5. java 并发——理解 wait / notify / notifyAll

    一.前言 前情简介: java 并发--内置锁 java 并发--线程 java 面试是否有被问到过,sleep 和 wait 方法的区别,关于这个问题其实不用多说,大多数人都能回答出最主要的两点区别 ...

  6. Java多线程中wait, notify and notifyAll的使用

    本文为翻译文章,原文地址:http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example 在Java的Obje ...

  7. 多线程-4.wait() notify() notifyAll() 生产者消费者模型

    1.wait()方法 该方法继承于Object类.在调用obj.wait()方法后,当前线程会失去obj的锁.待其他线程调用obj.notify()或notifyAll()方法后进入锁等待池,争抢到锁 ...

  8. Java多线程技术-wait/notify/join

    wait/notify的作用 wait()方法的作用是使当前执行代码的线程进行等待,wait()是Object类的方法,用来将当前线程置入预执行队列中,并且在wait()所在的代码处停止执行,直到接到 ...

  9. Java多线程wait和notify协作,按序打印abc

    有一个经典的多线程面试题:启三个线程,按序打印ABC 上代码: package cn.javaBase.study_thread1; class MyRunnable1 implements Runn ...

随机推荐

  1. jquery 拓展方法

    摘抄自(http://hi.baidu.com/jjjvzugcpmcdmor/item/0e32a89c36a18544f04215d7) $.fn是指jquery的命名空间,加上fn上的方法及属性 ...

  2. Androidproject夹

    创建一个Android应用 File -> New -> Android Application Project 填写应用名称.project名称.包名 设置project的相关信息.默认 ...

  3. 为Delphi程序增加UAC功能(每个步骤都很详细)

    相关资料:http://bbs.csdn.net/topics/320071356# 操作方法: 在Source\VCL目录下应该有这样两个文件sample.manifest和WindowsXP.rc ...

  4. IE6,IE7,IE8下报JS错误:expected identifier, string or number的原因及解决的方法

    今天在调试一个页面的时候遇到一个问题,在IE9下执行得非常好的脚本,在IE8里打开的时候弹出错误:expected identifier, string or number,依照经验,应该是定义对象的 ...

  5. mongodb时间戳转换成格式化时间戳

    db.pay_order.find({"id":"5332336532"},{"tradeNo":true,"status&quo ...

  6. Hawk-数据抓取工具

    Hawk-数据抓取工具:简明教程   Hawk: Advanced Crawler& ETL tool written in C#/WPF 1.软件介绍 HAWK是一种数据采集和清洗工具,依据 ...

  7. android画笔错位问题的解决

    下面的画画板的代码: public class MainActivity extends Activity { private ImageView iv; private Bitmap baseBit ...

  8. 类是公共,它应该被命名为.java文件声明

    当类的设置public时间,,public只要类的文件名必须是相同的,..这种错误可能发生在不同的

  9. 在word 中复选框划勾或叉的方法

    输入大写字母R.大写字母Q ,然后将字体改为Wingdings 2, 就分离得到带框的勾和叉.

  10. zoj3471(状压dp)

    题目连接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4257 题意:不超过10种气体,两两之间相互碰撞可以产生一定的能量,如 ...