wait(),notify()和notifyAll()都是Java基类java.lang.Object的方法。

通俗解释
wait():在当前线程等待其它线程唤醒。
notify(): 唤醒一个线程正在等待这个对象的监视器。
notifyAll(): 唤醒在这个对象监视器上等待的所有线程。
这三个方法,都是Java语言提供的实现线程间阻塞(Blocking)和控制进程内调度(inter-process communication)的底层机制。
下面通过一个生产者/消费者的例子来讲解这三个方法的使用

/**
* 消费者
* Created by Wiki on 16/1/28.
*/
public class Customer implements Runnable {
private String name;
private Channel channel; public Customer(String name, Channel channel) {
this.name = name;
this.channel = channel;
} @Override
public void run() {
while (true) {
Good good = channel.get();
if (good != null) {
System.out.println(name + " 获得商品:" + good.getName());
} else {
synchronized (channel) {
try {
System.out.println(name + " 进入等待");
channel.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
/**
* 生产者
* Created by Wiki on 16/1/28.
*/
public class Producer implements Runnable {
private static volatile int goodNumber = 0; private String name;
private Channel channel; public Producer(String name, Channel channel) {
this.name = name;
this.channel = channel;
} @Override
public void run() {
while (true) {
int sleep = new Random().nextInt(2000);
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
Good good = new Good("商品-编号" + (++goodNumber));
System.out.println(name + " 生产商品:" + good.getName());
channel.put(good);
}
}
}
/**
* 商品
* Created by Wiki on 16/1/28.
*/
public class Good {
private String name; public Good(String name) {
this.name = name;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}
/**
* 消费通道
* Created by Wiki on 16/1/28.
*/
public class Channel {
private Queue<Good> goodList = new LinkedList<>(); public synchronized Good get() {
if (goodList.size() == 0) {
return null;
}
Good good = goodList.remove();
return good;
} public synchronized void put(Good good) {
goodList.add(good);
// notifyAll();
notify();
}
}
public class Main {

    public static void main(String[] args) {
Channel channel = new Channel();
new Thread(new Producer("生产者1", channel)).start();
new Thread(new Producer("生产者2", channel)).start();
new Thread(new Producer("生产者2", channel)).start(); new Thread(new Customer("消费者1", channel)).start();
new Thread(new Customer("消费者2", channel)).start();
new Thread(new Customer("消费者3", channel)).start();
}
}

运行结果分析一(notify):

每次生产一个商品调用notify时,都只唤醒一个消费者进行消费,唤醒原则是从等待时间最长的开始。

消费者1 进入等待
消费者2 进入等待
消费者3 进入等待
生产者1 生产商品:商品-编号1
消费者1 获得商品:商品-编号1
消费者1 进入等待
生产者2 生产商品:商品-编号2
消费者2 获得商品:商品-编号2
消费者2 进入等待
生产者2 生产商品:商品-编号3
消费者3 获得商品:商品-编号3
消费者3 进入等待
生产者1 生产商品:商品-编号4
消费者1 获得商品:商品-编号4
消费者1 进入等待
生产者1 生产商品:商品-编号5
消费者2 获得商品:商品-编号5
消费者2 进入等待
...

运行结果分析二(把notify改成notifyAll):

每生产一件商品时调用notifyAll,都会把所有的消费者唤醒。

消费者1 进入等待
消费者3 进入等待
消费者2 进入等待
生产者2 生产商品:商品-编号1
消费者3 进入等待
消费者2 获得商品:商品-编号1
消费者1 进入等待
消费者2 进入等待
生产者2 生产商品:商品-编号2
消费者2 获得商品:商品-编号2
消费者1 进入等待
消费者3 进入等待
消费者2 进入等待
生产者2 生产商品:商品-编号3
消费者2 获得商品:商品-编号3
...

来源:http://www.taoweiji.cn/index.php/archives/112

通过生产者消费者模式例子讲解Java基类方法wait、notify、notifyAll的更多相关文章

  1. Java设计模式—生产者消费者模式(阻塞队列实现)

    生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...

  2. Java 生产者消费者模式详细分析

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  3. java ReentrantLock结合条件队列 实现生产者-消费者模式 以及ReentratLock和Synchronized对比

    package reentrantlock; import java.util.ArrayList; public class ProviderAndConsumerTest { static Pro ...

  4. 【多线程】java多线程实现生产者消费者模式

    思考问题: 1.为什么用wait()+notify()实现生产者消费者模式? wait()方法可以暂停线程,并释放对象锁 notify()方法可以唤醒需要该对象锁的其他线程,并在执行完后续步骤,到了s ...

  5. java 多线程 22 :生产者/消费者模式 进阶 利用await()/signal()实现

    java多线程15 :wait()和notify() 的生产者/消费者模式 在这一章已经实现了  wait/notify 生产消费模型 利用await()/signal()实现生产者和消费者模型 一样 ...

  6. 基于Java 生产者消费者模式(详细分析)

    Java 生产者消费者模式详细分析 本文目录:1.等待.唤醒机制的原理2.Lock和Condition3.单生产者单消费者模式4.使用Lock和Condition实现单生产单消费模式5.多生产多消费模 ...

  7. Java设计模式之生产者消费者模式

    Java设计模式之生产者消费者模式 博客分类: 设计模式 设计模式Java多线程编程thread 转载 对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一 ...

  8. java 多线程并发系列之 生产者消费者模式的两种实现

    在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...

  9. java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】

    java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...

随机推荐

  1. SQL Server跨服务器的数据库迁移

    1. 使用sql server task中back up 任务,保存为*.bak 文件. 2. 在另一个server中restore database,如果已经存在这个database,会覆盖之前的数 ...

  2. 王爽-汇编语言-综合研究一-搭建简易C环境

    (一) 学习过程: 整个过程分为两个部分: 第一:将TC2.0的环境使用虚拟软盘复制到DOS虚拟机中: 打开WinImage,fileànew,由于TC2.0的环境解压后为2.02M,所以我们在Sta ...

  3. C复数的四则运算

    #include<stdio.h> void judge(int True,int Fake) {     if (True == 0)     {         if (Fake == ...

  4. font-face跨域办法

    font-face是现在比较流行的技术,可以矢量化你的图标,更改颜色方便等等.如果你想更进一步了解他,请点击这里(CSS3 icon font完全指南)今晚有网友问到font-face跨域在nginx ...

  5. C++二级指针第三种内存模型

    #include "stdio.h" #include "stdlib.h" #include "string.h" void main() ...

  6. C# IEnumerable,Lambda表达式和 Parallel并行编程的用法

    以前一直主要做C++和C方面的项目,对C#不太了解熟悉,但听说不难,也就一直没有在意学习C#方面的知识.今天有个C#项目,需要做些应用的扩展,同时修改一些bug.但看了C#代码,顿时觉得有些不适应了. ...

  7. 不能运行,:framework not found SenTestingKit

    1. 真机调试,提示 ld: framework not found SenTestingKit $(DEVELOPER_LIBRARY_DIR)/Frameworks  

  8. php笔试题(1)--转载

    一份不错的php面试题,附答案,有准备换工作的同学可以参考一下.一.基础题1. 写出如下程序的输出结果 <?php     $str1 = null;     $str2 = false;    ...

  9. C#函数式编程之部分应用

    何谓函数式编程 相信大家在实际的开发中,很多情况下完成一个功能都需要借助多个类,那么我们这里的基本单元就是类.而函数式编程则更加细化,致使我们解决一个功能的基本单元是函数,而不是类,每个功能都是由多个 ...

  10. Python爬虫 -- 抓取电影天堂8分以上电影

    看了几天的python语法,还是应该写个东西练练手.刚好假期里面看电影,找不到很好的影片,于是有个想法,何不搞个爬虫把电影天堂里面8分以上的电影爬出来.做完花了两三个小时,撸了这么一个程序.反正蛮简单 ...