Java实现生产者消费者的方式有:wait && notify、BlockingQueue、Lock && Condition等

wait、notify注意事项:
(1)可以使用wait()和notify()方法在Java中实现线程间通信。不只是一个或两个线程,而是多个线程可以使用这些方法相互通信。
(2)在synchronized方法或synchronized块中调用wait(),notify()和notifyAll()方法,否则JVM将抛出IllegalMonitorStateException。
(3)从while(条件)循环调用wait和notify方法,而不是从if()块调用,因为要重复检查条件,而不仅仅是一次。
(4)多使用notifyAll方法而不是notify。

下面是wait、notify等待通知实现的生产者-消费者模式:
生产者:

/**
* 生产者
*
* @author monkjavaer
* @date 2018/12/15 11:13
*/
public class Producer implements Runnable {
/**
* 产品容器
*/
private final List<Integer> container; public Producer(List<Integer> container) {
this.container = container;
} /**
* 生产者生产方法
*
* @throws InterruptedException
*/
private void produce() throws InterruptedException {
//产品容器容量
int capacity = 5;
synchronized (container) {
//当容器已满,暂停生产
while (container.size() == capacity) {
System.out.println("...容器已经满了,暂停生产...");
container.wait();
}
Random random = new Random();
int p = random.nextInt(50);
//模拟1秒生产一个产品
TimeUnit.MILLISECONDS.sleep(1000);
System.out.println("生产产品:" + p);
container.add(p);
container.notifyAll();
}
} @Override
public void run() {
while (true) {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("produce error");
}
}
}
}

  消费者:

/**
* 消费者
* @author monkjavaer
* @date 2018/12/15 11:13
*/
public class Consumer implements Runnable{ /**
* 产品容器
*/
private final List<Integer> container; public Consumer(List<Integer> container) {
this.container = container;
} /**
* 消费者消费产品
*/
private void consume() throws InterruptedException {
synchronized (container){
while (container.isEmpty()){
System.out.println("...容器是空的,暂停消费...");
container.wait();
}
Integer p = container.remove(0);
//模拟1秒消费一个产品
TimeUnit.MILLISECONDS.sleep(1000);
System.out.println("消费产品:" + p);
container.notifyAll();
}
}
@Override
public void run() {
while (true){
try {
consume();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("consume error");
}
}
}
}

  测试:

public class ProducerConsumerTest {
public static void main(String[] args) {
List<Integer> container = new ArrayList<>();
Thread producer = new Thread(new Producer(container));
Thread consumer = new Thread(new Consumer(container));
producer.start();
consumer.start();
}
}

  输出:

生产产品:14
生产产品:17
消费产品:14
生产产品:0
生产产品:39
生产产品:4
生产产品:3
...容器已经满了,暂停生产...
消费产品:17
消费产品:0
消费产品:39
消费产品:4
消费产品:3
...容器是空的,暂停消费...
生产产品:25
生产产品:33
生产产品:17
消费产品:25
消费产品:33
消费产品:17
...容器是空的,暂停消费...

  

wait、notify应用场景(生产者-消费者模式)的更多相关文章

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

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

  2. 10 阻塞队列 & 生产者-消费者模式

    原文:http://www.cnblogs.com/dolphin0520/p/3932906.html 在前面我们接触的队列都是非阻塞队列,比如PriorityQueue.LinkedList(Li ...

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

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

  4. Handler机制与生产者消费者模式

    本文梳理了 Handler 的源码,并详细阐述了 Handler 与生产者消费者模式的关系,最后给出了多版自定义 Handler 实现.本文首发于简书,重新整理发布. 一.Handler Handle ...

  5. java多线程 生产者消费者模式

    package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...

  6. 转:Task任务调度实现生产者消费者模式

    我们经常会遇到生产者消费者模式,比如前端各种UI操作事件触发后台逻辑等.在这种典型的应用场景中,我们可能会有4个业务处理逻辑(下文以P代表生产者,C代表消费者): 1. FIFO(先进先出)      ...

  7. 使用BlockingQueue的生产者消费者模式

    BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利.使用场景. 首先它是一个队列,而一个队 ...

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

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

  9. 【多线程】--生产者消费者模式--Lock版本

    在JDK1.5发布后,提供了Synchronized的更优解决方案:Lock 和 Condition 我们使用这些新知识,来改进例子:[多线程]--生产者消费者模式--Synchronized版本 改 ...

随机推荐

  1. redis在linux的安装和开机启动(二)

    编译 安装 makefile已经存在 执行make 即可 make之后, 自动创建可运行的脚本文件, 不需要再执行 install了. 将脚本文件, 拷贝到指定位置, 就可以了. 手动创建目录, 需要 ...

  2. $CF1153A\ Serval\ and\ Bus$

    看大佬的代码都好复杂(不愧是大佬\(orz\) 蒟蒻提供一种思路 因为求的是最近的车对吧\(qwq\) 所以我们可以用一个\(while\)循环所以没必要去用什么 \(for...\) 至于这是\(d ...

  3. [Usaco2018 Open]Talent Show

    Description FarmerJohn要带着他的N头奶牛,方便起见编号为1-N,到农业展览会上去,参加每年的达牛秀!他的第i头奶牛重量为wi,才艺水平为ti,两者都是整数.在到达时,Farmer ...

  4. 思维题 URAL 1409 Two Gangsters

    题目传送门 /* 思维题:注意题目一句话:At some moment it happened so that they shot one and the same can. 如果两个人都有射中的话, ...

  5. 微信JSSDK支付

    var appId,timeStamp,nonceStr,package,signType,paySign; function goumai(){ $.confirm({ title: '确认购买', ...

  6. JavaScript开发心得--如何传递某行数据给下一页

    1, 应用场景 在某个html页面显示一批数据,如20个用户的名称.年龄等,每行都要一个编辑按钮,点击编辑后,将此行数据带入某个专门的编辑页进行显示,修改后保存. 问题是 点击编辑按钮后,如何得知要编 ...

  7. SVN的三种merge方式【转】

    SVN的merge操作是为了保证主干(trunk)和分支(branch)同步,merge方式有: 1.Merge a range of revisions(合并一个范围的版本) 2.Reintegra ...

  8. sql server nullif的使用技巧,除数为零的处理技巧

    在sql server中做除法处理的时候,我们经常需要处理除数为零的情况,因为如果遇到这种情况的时候,sqlserver会抛出遇到以零作除数错误的异常,我们总不希望把这个异常显示给用户吧. 做个会报这 ...

  9. Git——基本操作

    Shell 基本概念 shell俗称壳,为使用者提供使用界面,例如DOS下command以及后来的cmd.exe shell分类 图形界面shell,提供友好的可视化界面,例如windows操作界面, ...

  10. jsp学习笔记 - 内置对象 session

    1.session 主要用来用户的登录和注销 设置用户名,获取用户名 session.setAttribute("username","johnson"); s ...