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. post和get区别,其他答案真的太坑

    原理: get和post都是http定义与服务器交互的方法,还有put,delete url是网络上的资源,那么http中的get,post,put,delete对应的就是对这个资源的查,改,增,删四 ...

  2. 二分图最大匹配(匈牙利算法) POJ 3041 Asteroids

    题目传送门 /* 题意:每次能消灭一行或一列的障碍物,要求最少的次数. 匈牙利算法:把行和列看做两个集合,当有障碍物连接时连一条边,问题转换为最小点覆盖数==二分图最大匹配数 趣味入门:http:// ...

  3. layer父页获取弹出层输入框里面的值

    主要是因为修改功能,原来页面填写数据如图 改为 其中点击填写明细弹出框 填写完毕后点击确认返回,同事这里因为她是存的多表,所以点击确认就直接保存数据了,改的这个功能原本保存是整体保存,我就不想改原来的 ...

  4. Ajax动态加载数据

    前言: 1.这个随笔实现了一个Ajax动态加载的例子. 2.使用.net 的MVC框架实现. 3.这个例子重点在前后台交互,其它略写. 开始: 1.控制器ActionResult代码(用于显示页面) ...

  5. CF 334 div.2-D Moodular Arithmetic

    思路: 易知k = 0的时候答案是pp-1,k = 1的时候答案是pp. 当k >= 2的时候,f(0) = 0,对于 1 <= n <= p - 1,如果f(n)确定,由题意可知f ...

  6. get、post、put、delete、head请求方式

    对资源的增,删,改,查操作,其实都可以通过GET/POST完成,不一定要用PUT和DELETE. 一:Jersey框架,实现了restful风格,常用的注解@GET.@POST.@PUT.@DELET ...

  7. JAVA环境变量配置后未变动配置失效处理

    环境: Windows 7 x64 配置方案来源于教程: http://www.mamicode.com/info-detail-563355.html 配置方案出现的问题: 正确配置JAVA环境变量 ...

  8. HTML <section> 标签

    实例 文档中的区段,解释了 PRC: <section>   <h1>PRC</h1>   <p>The People's Republic of Ch ...

  9. nz-card头部右侧添加东西

    <nz-card [nzBordered]="true" nzTitle="卡片标题" [nzExtra]="extraTemplate1&qu ...

  10. 07C语言程序语句

    C语言程序语句 判断语句 if(表达式) {语句} #include <stdio.h> int main(){ printf("请输入2个数字:"); int a,b ...