java中,wait和notify这两个方法是一对,wait方法阻塞当前线程,而notify是唤醒被wait方法阻塞的线程。

    首先,需要说明的是,wait和notify方法都是Object的实例方法,要执行这两个方法,有一个前提就是,当前线程必须获其对象的monitor(俗称“锁”),否则会抛出IllegalMonitorStateException异常,所以这两个方法必须在同步块代码里面调用,经典的生产者和消费者模型就是使用这两个方法实现的。
    当前线程A获得对象obj的monitor,然后进入临界区(同步代码块),调用对象obj的wait方法,则线程A释放obj的monitor(执行了obj的wati方法之后,就会释放obj的monitor,不用等到执行完临界区,因为线程A会被阻塞在当前这个位置,同时cpu的相关寄存器会记住当前位置的堆栈信息),然后进入阻塞状态,同时线程A让出cpu,不再参与cpu的竞争,但是还会同时wait方法内部会不断地轮询线程A的InterruptStatus状态位(其实导致阻塞的方法一般都会做这个操作,就是不断地轮询中断状态位,以判断当前被阻塞的线程是否被提前取消了),以判断当前阻塞的状态是否会被中断(这里有点小矛盾,照理线程A不再参与cpu的竞争,又还不断轮询中断状态位,这个我还要研究下,有知道的可以留言评论指出,谢谢),等待其他线程调用A的notify(或notifyAll)来唤醒;然后线程B获取的obj的monitor之后,进去临界区,执行obj的notify方法,这时候,有点和wait方法不一样,就是调用了obj的notify之后,不会立刻释放obj的monitor同时唤醒线程A,而是要等到线程B执行完同步块代码,出了临界区,这时候才会释放obj的monitor,同时唤醒线程A,这时候线程A就会从新参与cpu的竞争,就有机会(因为可能其他线程也在竞争obj的monitor,如果之前有几个线程都在等待被obj的notify唤醒,则这时候就会有几个线程同时被唤醒,唤醒之后,因为obj的monitor同一时刻只允许一个线程拥有,所以被唤醒的几个线程究竟谁先获得obj的monitor继续往下面执行呢?这个就是根据操作系统的调度算法了。一个执行完同步块代码,释放obj的monitor之后,其他被唤醒的线程才会一个一个竞争获取obj的monitor,继续执行其wait方法后面的代码...)获取的obj的monitor,等到线程A重新获得obj的monitor之后,线程A会进入临界区,从wait方法后面继续执行(注意:这里进入临界区之后,不会从新从头执行临界区代码块,而会根据之前调用wait方法阻塞的时候,cpu记住的堆栈信息,会直接从wait方法后面的代码开始继续往下执行),直到出了临界区,释放obj的monitor。
    这里还有一个要注意的问题就是,wait和notify调用的顺序一定要注意先后,如果先调用了obj的notify,然后才调用obj的wait方法的话,则调用了wait方法被阻塞的线程则不会被唤醒,会一直处于阻塞状态。
    以下是我参考(http://www.cnblogs.com/hapjin/p/5492645.html)代码做的实践:
    Service类
/**
* Created by regis on 2017/4/23.
*/
public class Service {
public void testMethod(Object lock) {
try {
synchronized (lock) {
System.out.println("begin wait() ThreadName=" + Thread.currentThread().getName());
lock.wait();
if (Thread.currentThread().getName().equals("Thread-1")) {
Thread.sleep(50000);
}
System.out.println("end wait() ThreadName=" + Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void synNotifyMethod(Object lock) {
synchronized (lock) {
System.out.println("begin notify() ThreadName=" + Thread.currentThread().getName());
lock.notifyAll();
System.out.println("end notify() ThreadName=" + Thread.currentThread().getName());
}
}
}
    SynNotifyMethodThread类
/**
* Created by regis on 2017/4/23.
*/
public class SynNotifyMethodThread extends Thread {
private Object lock;
public SynNotifyMethodThread(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
Service service = new Service();
service.synNotifyMethod(lock);
}
}
    测试类
/**
* Created by regis on 2017/4/20.
*/
public class Test {
public static void main(String[] args) {
Object lock = new Object();
ThreadA a = new ThreadA(lock);
a.start();
ThreadA b = new ThreadA(lock);
b.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
SynNotifyMethodThread c = new SynNotifyMethodThread(lock);
c.start();
}
}
    ThreadA类
/**
* Created by regis on 2017/4/23.
*/
public class ThreadA extends Thread{
private Object lock;
public ThreadA(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
Service service = new Service();
service.testMethod(lock);
}
}
参考:http://www.cnblogs.com/hapjin/p/5492645.html
 

java中wait和notify的关系的更多相关文章

  1. 计算机基础--Java中int char byte的关系

    计算机基础--Java中int char byte的关系 重要:一个汉字占用2byte,Java中用char(0-65535 Unicode16)型字符来存字(直接打印输出的话是字而非数字),当然要用 ...

  2. java中接口与多重继承的关系

    在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制.正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力.abstract class和int ...

  3. Java中wait()和notify()方法的使用

    1. wait方法和notify方法 这两个方法,包括notifyAll方法,都是Object类中的方法.在Java API中,wait方法的定义如下: public final void wait( ...

  4. java中wait和notify

    在JAVA中,是没有类似于PV操作.进程互斥等相关的方法的.JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的 ...

  5. Java面试题:Java中的集合及其继承关系

    关于集合的体系是每个人都应该烂熟于心的,尤其是对我们经常使用的List,Map的原理更该如此.这里我们看这张图即可: 1.List.Set.Map是否继承自Collection接口? List.Set ...

  6. 线程:Java中wait、notify、notifyAll使用详解

    基础知识 首先我们需要知道,这几个都是Object对象的方法.换言之,Java中所有的对象都有这些方法. public final native void notify(); public final ...

  7. Java中wait()与notify()理解

    通常,多线程之间需要协调工作.例如,浏览器的一个显示图片的线程displayThread想要执行显示图片的任务,必须等待下载线程 downloadThread将该图片下载完毕.如果图片还没有下载完,d ...

  8. java 中 热部署与卸载关系

    今天发现早年在大象笔记中写的一篇笔记,之前放在ijavaboy上的,现在它已经访问不了了.前几天又有同事在讨论这个问题.这里拿来分享一下. 在web应用开发或者游戏服务器开发的过程中,我们时时刻刻都在 ...

  9. Java中类名与文件名的关系

    1.Java保存的文件名必须与类名一致: 2.如果文件中只有一个类,文件名必须与类名一致: 3.一个Java文件中只能有一个public类: 4.如果文件中不止一个类,文件名必须与public类名一致 ...

随机推荐

  1. C++友元(友元函数、友元类和友元成员函数)

    友元(友元函数.友元类和友元成员函数) C++ 有些情况下,允许特定的非成员函数访问一个类的私有成员,同时仍阻止一般的访问,这是很方便做到的.例如被重载的操作符,如输入或输出操作符,经常需要访问类的私 ...

  2. Elasticsearch学习(3) spring boot整合Elasticsearch的原生方式

    前面我们已经介绍了spring boot整合Elasticsearch的jpa方式,这种方式虽然简便,但是依旧无法解决我们较为复杂的业务,所以原生的实现方式学习能够解决这些问题,而原生的学习方式也是E ...

  3. django数据模型中关于on_delete的使用

    django数据模型中关于on_delete的使用 class BookModel(models.Model): """ 书籍表 """ b ...

  4. bzoj4199: [Noi2015]品酒大会(后缀数组)

    题目描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战 两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒师 Rainb ...

  5. 2017qcon大会的一点想法(安全人才如何不被淘汰?)

    2017 qcon 上海专门设立了“直击黑产,业务安全的攻与防”专题,通过这次专题的了解和学习,让我对黑产的攻防有了更深入认识. 1. 安全防护趋势 2017 qcon 上海专门设立了“直击黑产,业务 ...

  6. PHP实现用户在线状态检测

    这个是基于ThinkPHP框架的,其他的可以自己根据需求改 1.先新建一个tags.php文件,放在配置目录Conf下. <?php  /*  * 添加行为  *  */  return arr ...

  7. [Swift实际操作]八、实用进阶-(8)使用performSegue在故事板页面之间进行数据传递

    本文将演示故事板页面之间的数据传递.首先在一个空白项目中,打开项目自带的故事板文件(Main.storyboard).故事板中已经拥有了一个视图控制器,点击选择该视图控制器.然后依此点击[Editor ...

  8. python 强大的工具

    numpy Python科学计算的基础包 安装工具 pip3 install numpy pandas包含了高级的数据结构和操作工具,它们使得Python数据分析更加快速和容易. 安装工具 pip3 ...

  9. js中的valueOf与toString

    所有对象继承了两个转换方法: 第一个是toString(),它的作用是返回一个反映这个对象的字符串 第二个是valueOf(),它的作用是返回它相应的原始值 一般来说,对象到字符串的转换经过了如下步骤 ...

  10. POJ1475 Pushing Boxes(双搜索)

    POJ1475 Pushing Boxes  推箱子,#表示墙,B表示箱子的起点,T表示箱子的目标位置,S表示人的起点 本题没有 Special Judge,多解时,先最小化箱子被推动的次数,再最小化 ...