// The standard idiom for calling the wait
synchronized(sharedObject) {
while(condition){
sharedObject.wait();// Releases lock, and reacquires on wake up
}
// do action based upon condition e.g. take or put into queue
}

使用wait和notify函数的规范代码模版。

在while循环里使用wait的目的:是在线程被唤醒前后都持续检查条件是否被满足,如果条件并未改变,wait被调用之前notify的唤醒通知就来了,那个这个线程并不能保证被唤醒,有坑会导致死锁的问题。

 public class ProducerConsumer {
public static void main (String args[]) {
Queue<Integer> buffer = new LinkedList<>();
int maxSize = 10;
Thread producer = new Producer(buffer, maxSize, "PRODUCER");
Thread consumer = new Producer(buffer, maxSize, "CONSUMER");
producer.start();
consumer.start();
}
}

在上面代码中,声明了一个LinkedList作为缓冲区队列(在java中,LinkedList实现了队列的接口)。

class Producer extends Thread  {
private Queue<Integer> queue;
private int maxSize;
public Producer(Queue<Integer> queue, int maxSize, String name) {
super(name);
this.queue = queue;
this.maxSize = maxSize;
} @Override
public void run () {
while (true) {
synchronized (queue) { // 其它线程不能在我们检查条件时改变这个队列
while (queue.size() == maxSize) {
try {
// Queue is full
// Producer thread waiting for
// consumer to take something from queue
queue.wait();
} catch (Exception e) {
e.printStackTrace();
}
Random random = new Random();
int producerValue = random.nextInt();
queue.add(producerValue);
queue.notifyAll();
}
}
}
}
}

如上代码为生产者,其在无限循环中持续往LinkedList里插入随机整数直到LinkedList满。如果队列满了,那么生产者线程会在消费者线程消耗掉队列里的任意一个整数,并用notify通知生产者线程之前持续等待。

 class Consumer extends Thread {
private Queue<Integer> queue;
private int maxSize;
public Consumer (Queue<Integer> queue, int maxSize, String name ){
super(name);
this.queue = queue;
this.maxSize= maxSize;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
// queue is empty;
// Consumer thread is waiting
// for producer thread to put something in queue
try {
queue.wait();
} catch (Exception e) {
e.printStackTrace();
}
print("Consumer value : " + queue remove());
queue.notifyAll();
}
}
}
}
}

注意:

1. 你可以使用wait和notify函数来实现线程间通信,你可以用它们来实现多线程之间的通信。

2. 永远在synchronized的函数或者对象里使用wait、notify、notifyAll,不然java虚拟机会生成IllgalMonitorStateException。

3. 永远在while循环里而不是在if语句下使用wait,这样,循环会在线程睡眠前后都检查wait的条件,并在条件实际上并未改变的情况下处理唤醒通知。

4. 永远在多线程间共享的对象(生产者消费者模型里即缓冲区队列)上使用wait。

Producer - Consumer Pattern:

Consumer:

sunchronized (obj) {
while (!workToDo) {
obj.wait();
}
// get next item from this queue
workToDo = false;
}
// do work on the item

Producer:

 synchronized (obj) {
if (!workToDo) {
// add work to queue
workToDo = true;
}
obj.notifyAll();
}

Java 生产者模式 消费者模式的更多相关文章

  1. java生产者与消费者模式

    前言: 生产者和消费者模式是我们在学习多线程中很经典的一个模式,它主要分为生产者和消费者,分别是两个线程, 目录 一:生产者和消费者模式简介 二:生产者和消费者模式的实现 声明:本例来源于java经典 ...

  2. Java并发编程(4)--生产者与消费者模式介绍

    一.前言 这种模式在生活是最常见的,那么它的场景是什么样的呢? 下面是我假象的,假设有一个仓库,仓库有一个生产者和一个消费者,消费者过来消费的时候会检测仓库中是否有库存,如果没有了则等待生产,如果有就 ...

  3. Java多线程设计模式(2)生产者与消费者模式

    1 Producer-Consumer Pattern Producer-Consumer Pattern主要就是在生产者与消费者之间建立一个“桥梁参与者”,用来解决生产者线程与消费者线程之间速度的不 ...

  4. java 线程并发(生产者、消费者模式)

    线程并发协作(生产者/消费者模式) 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型“生产者/消费者模式”. Ø 什么是生产者? 生产者指的是负责生产数 ...

  5. java进阶(40)--wait与notify(生产者与消费者模式)

    文档目录: 一.概念 二.wait的作用 三.notify的作用 四.生产者消费者模式 五.举例 ---------------------------------------分割线:正文------ ...

  6. 使用libuv实现生产者和消费者模式

    生产者和消费者模式(Consumer + Producer model) 用于把耗时操作(生产线程),分配给一个或者多个额外线程执行(消费线程),从而提高生产线程的响应速度(并发能力) 定义 type ...

  7. condition版生产者与消费者模式

    1.简介 在爬虫中,生产者与消费者模式是经常用到的.我能想到的比较好的办法是使用redis或者mongodb数据库构造生产者消费者模型.如果直接起线程进行构造生产者消费者模型,线程容易假死,也难以构造 ...

  8. 【爬虫】Condition版的生产者和消费者模式

    Condition版的生产者和消费者模式 threading.Condition 在没有数据的时候处于阻塞状态,有数据可以使用notify的函数通知等等待状态的线程运作 threading.Condi ...

  9. 【爬虫】Load版的生产者和消费者模式

    ''' Lock版的生产者和消费者模式 ''' import threading import random import time gMoney = 1000 # 原始金额 gLoad = thre ...

  10. Java生产者与消费者(上)

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 生产与消费者模式,是编程中最常用的模式之一,在多线程中应用比较明显.个人理解:在自助餐厅,厨师在不断 ...

随机推荐

  1. Sample Apps by Android Team -- Amazed

    Sample Apps by Android Team 代码下载:http://pan.baidu.com/s/1eSNmdUE , 代码原地址:https://code.google.com/arc ...

  2. WebService - 怎样提高WebService性能 大数据量网络传输处理

    直接返回DataSet对象 返回DataSet对象用Binary序列化后的字节数组 返回DataSetSurrogate对象用Binary序列化后的字节数组 返回DataSetSurrogate对象用 ...

  3. jQuery Moblie 学习之page、button、theme、panel、listview、controlgroup、navbar等(一)

    1.jQTouch jQTouch与jQuery Moblie十分相似,也是一个jQuery插件,同样也支持HTML页面标签驱动,实现移动设备视图切换效果.不同的是它是专为WebKit内核的浏览器打造 ...

  4. Android 注解工具 ButterKnife

    Butter Knife 是 Android 视图字段和方法绑定,使用注解处理来生成样板代码. 主要特性: 在字段使用 @FindView消除findViewById调用 使用 @FindViews在 ...

  5. 【翻译十一】java-原子性操作

    Atomic Access In programming, an atomic action is one that effectively happens all at once. An atomi ...

  6. HTML5_Canvas_属性、定义及方法

    一.简单图形,整套的属性和方法专门用于绘制矩形:1.fillStyle可以设置为CSS颜色.一个图案或一种颜色渐变.fillStyle默认是纯黑色,你可以设置成你喜欢的任意颜色.只要页面打开着,每个绘 ...

  7. android 入门-库的生成jar 和引用jar

    开发环境 1.eclipse 2.android studio 步骤 1.在eclipse 生成 jar包 2.在android studio 引用 jar包 实现步骤 1.在eclipse 创建一个 ...

  8. windows64系统中mysql64位绿色安装

    将下载压缩包解压到任意目录 配置安装文件: # For advice on how to change settings please see# http://dev.mysql.com/doc/re ...

  9. Effective C++ 之 Item 4:确定对象被使用前已先被初始化

    Effective C++ Chapter 1. 让自己习惯C++ (Accustoming Yourself to C++) Item 4. 确定对象被使用前已先被初始化 (Make sure th ...

  10. Intent传递类实例

    发送方: Intent intent = new Intent(); intent.setClass(mContext, HomeDetailReportActivity.class); intent ...