Java 生产者模式 消费者模式
// 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 生产者模式 消费者模式的更多相关文章
- java生产者与消费者模式
前言: 生产者和消费者模式是我们在学习多线程中很经典的一个模式,它主要分为生产者和消费者,分别是两个线程, 目录 一:生产者和消费者模式简介 二:生产者和消费者模式的实现 声明:本例来源于java经典 ...
- Java并发编程(4)--生产者与消费者模式介绍
一.前言 这种模式在生活是最常见的,那么它的场景是什么样的呢? 下面是我假象的,假设有一个仓库,仓库有一个生产者和一个消费者,消费者过来消费的时候会检测仓库中是否有库存,如果没有了则等待生产,如果有就 ...
- Java多线程设计模式(2)生产者与消费者模式
1 Producer-Consumer Pattern Producer-Consumer Pattern主要就是在生产者与消费者之间建立一个“桥梁参与者”,用来解决生产者线程与消费者线程之间速度的不 ...
- java 线程并发(生产者、消费者模式)
线程并发协作(生产者/消费者模式) 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型“生产者/消费者模式”. Ø 什么是生产者? 生产者指的是负责生产数 ...
- java进阶(40)--wait与notify(生产者与消费者模式)
文档目录: 一.概念 二.wait的作用 三.notify的作用 四.生产者消费者模式 五.举例 ---------------------------------------分割线:正文------ ...
- 使用libuv实现生产者和消费者模式
生产者和消费者模式(Consumer + Producer model) 用于把耗时操作(生产线程),分配给一个或者多个额外线程执行(消费线程),从而提高生产线程的响应速度(并发能力) 定义 type ...
- condition版生产者与消费者模式
1.简介 在爬虫中,生产者与消费者模式是经常用到的.我能想到的比较好的办法是使用redis或者mongodb数据库构造生产者消费者模型.如果直接起线程进行构造生产者消费者模型,线程容易假死,也难以构造 ...
- 【爬虫】Condition版的生产者和消费者模式
Condition版的生产者和消费者模式 threading.Condition 在没有数据的时候处于阻塞状态,有数据可以使用notify的函数通知等等待状态的线程运作 threading.Condi ...
- 【爬虫】Load版的生产者和消费者模式
''' Lock版的生产者和消费者模式 ''' import threading import random import time gMoney = 1000 # 原始金额 gLoad = thre ...
- Java生产者与消费者(上)
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 生产与消费者模式,是编程中最常用的模式之一,在多线程中应用比较明显.个人理解:在自助餐厅,厨师在不断 ...
随机推荐
- Quartus II9.0 使用中文输入的方法
Quartus II可以用中文了 我们都知道高版本的quartus里面不支持中文,就连最新版的10.0也不支持,还好找到了一种方法,和大家分享一下: 具体步骤:quartus ——tools——o ...
- Android Programming: Pushing the Limits -- Chapter 3: Components, Manifests, and Resources
Android Components Manifest文件 Resource and Assets v\:* {behavior:url(#default#VML);} o\:* {behavior: ...
- logstash json和rubydebug 第次重启logstash都会把所有的日志读完 而不是只读入新输入的内容
查看一下agent端的shipper的配置: # cat logstash_test2.shipper.conf input { file { path => ["/apps/logs ...
- 无废话ExtJs 入门教程十四[文本编辑器:Editor]
无废话ExtJs 入门教程十四[文本编辑器:Editor] extjs技术交流,欢迎加群(201926085) ExtJs自带的编辑器没有图片上传的功能,大部分时候能够满足我们的需要. 但有时候这个功 ...
- VS2013 当前不会命中断点,还没有为该文档加载任何符号
方法一: 把ie的 调试 打开,然后调试的时候 会问你 是在新示例中打开 还是 当前示例,你选择当前的就行了.还有 建议你用 ie8.0的 开发者工具 调试 非常舒服 我已经 早就不用debuger ...
- Solr入门之(6)配置文件solrconfig.xml
solrconfig.xml包含了用于配置自身行为的绝大部分参数,其作用范围是当前core.该文件位于${solr_home}/solr/core1/conf/下. 参数列表概览: A.lib B.d ...
- ssh 免密码登陆
远程ssh登陆服务器或者其他机器时或者scp时,需要输入密码,感觉很麻烦,于是研究如何免密码登陆. step1:Client端生成公钥和密钥 执行命令 ssh-keygen 进入目录~/.ssh里面, ...
- BRIEF 特征描述子
Binary Robust Independent Elementary Features www.cnblogs.com/ronny 1. BRIEF的基本原理 我们已经知道SIFT特征采用了128 ...
- URAL 1966 Cycling Roads 点在线段上、线段是否相交、并查集
F - Cycling Roads Description When Vova was in Shenzhen, he rented a bike and spent most of the ...
- CSS 基本1
HTML元素可以分为两种: 块级元素 内联元素(行内元素) 两者的区别在于以下三点: 块级元素会独占一行(即无法与其他元素显示在同一行内,除非你显示修改元素的 display 属性),而内联元素则都会 ...