为什么要使用生产者和消费者模式

在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这种生产消费能力不均衡的问题,所以便有了生产者和消费者模式。

什么是生产者消费者模式

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

这个阻塞队列就是用来给生产者和消费者解耦的。纵观大多数设计模式,都会找一个第三者出来进行解耦,如工厂模式的第三者是工厂类,模板模式的第三者是模板类。

生产者消费者模式实战

利用BlockingQueue

package com;

import java.util.Random;
import java.util.concurrent.BlockingQueue; public class Comsumer implements Runnable {
private BlockingQueue<PCData> queue;
private static final int SLEEPTIME = 1000;
public Comsumer(BlockingQueue<PCData> queue) {
this.queue = queue;
}
@Override
public void run() {
System.out.println("start Consumer Id:"+Thread.currentThread().getId());
Random r = new Random();
Boolean isrunning = true;
try {
while(isrunning){
PCData data = queue.take();
if(data != null){
System.out.println("Comsumer data:"+data);
Thread.sleep(r.nextInt(SLEEPTIME));
}
}
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}

  

package com;

import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; public class Producer implements Runnable{
private volatile boolean isRunning = true;
//内存缓冲区
private BlockingQueue<PCData> queue;
//总数 AtomicInteger
private static AtomicInteger count = new AtomicInteger();
private static final int SLEEPTIME = 1000; public Producer(BlockingQueue<PCData> queue){
this.queue = queue;
} public void run(){
PCData data = null;
Random r = new Random();
System.out.println("start producting id:"+ Thread.currentThread().getId());
while(isRunning){
try {
while(isRunning){
Thread.sleep(r.nextInt(SLEEPTIME));
data = new PCData(count.incrementAndGet());
if(!queue.offer(data,2,TimeUnit.SECONDS)){
System.out.println("加入队列失败");
}else{
System.out.println("Producer data:"+data);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
} public void stop(){
isRunning = false;
}
}

  

package com;

public class PCData {
private final int intData;
public PCData(int d){
intData = d;
} public PCData(String d){
intData = Integer.valueOf(d);
} public int getData(){
return intData;
} @Override
public String toString(){
return ""+intData;
}
}

  

package com;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue; public class Main {
public static void main(String[] args) throws InterruptedException{
BlockingQueue<PCData> queue = new LinkedBlockingQueue<>(10);
Producer p1 = new Producer(queue);
Producer p2 = new Producer(queue);
Producer p3 = new Producer(queue);
Comsumer c1 = new Comsumer(queue);
Comsumer c2 = new Comsumer(queue);
Comsumer c3 = new Comsumer(queue);
ExecutorService service = Executors.newCachedThreadPool();
service.execute(p1);
service.execute(p2);
service.execute(p3);
service.execute(c1);
service.execute(c2);
service.execute(c3);
Thread.sleep(10*1000);
p1.stop();
p2.stop();
p3.stop();
Thread.sleep(3000);
service.shutdown();
}
}

  利用notifyAll和wait

package com;

import java.util.List;

public class Consumer implements Runnable{
private List<PCData> queue;
public Consumer(List<PCData> queue){
this.queue = queue;
} @Override
public void run() {
while(true){
PCData data = null;
try {
synchronized (queue) {
if(queue.size() == 0){
System.out.println(Thread.currentThread().getId()+"队列为空,无法消费");
queue.notifyAll();
queue.wait();
}else{
data = queue.remove(0);
System.out.println(Thread.currentThread().getId()+"消费:"+data);
}
}
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

  

package com;

import java.util.List;
import java.util.Random; public class Producer implements Runnable {
private List<PCData> queue;
private int length; public Producer(List<PCData> queue,int length){
this.queue = queue;
this.length = length;
} @Override
public void run() {
while(true){
Random r = new Random();
PCData data = new PCData(r.nextInt(100));
try {
synchronized (queue) {
if(queue.size() >= length){
System.out.println(Thread.currentThread().getId()+"队列满了,无法加入 ");
queue.notifyAll();
queue.wait();
}else{
queue.add(data);
System.out.println(Thread.currentThread().getId()+"生产了:"+data);
}
}
Thread.sleep(1000);
} catch (InterruptedException e){
e.printStackTrace();
}
} } }

  

package com;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class Main {
public static void main(String[] args){
List<PCData> queue = new ArrayList<>();
int length =10;
Producer p1 = new Producer(queue, length);
Producer p2 = new Producer(queue, length);
Producer p3 = new Producer(queue, length);
Consumer c1 = new Consumer(queue);
Consumer c2 = new Consumer(queue);
Consumer c3 = new Consumer(queue);
ExecutorService service = Executors.newCachedThreadPool();
service.execute(p1);
service.execute(p2);
service.execute(p3);
service.execute(c1);
service.execute(c2);
service.execute(c3);
}
}

  

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

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

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

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

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

  3. java生产者/消费者模式实现——一生产者一消费者(操作值)

    胶多不粘话多不甜,直接上代码: 生产者类: /** * Created by 51304 on 2016/2/28. */ public class P { private String lock; ...

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

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

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

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

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

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

  7. Java 学习笔记 使用并发包ReentrantLock简化生产者消费者模式代码

    说明 ReentrantLock是java官方的一个线程锁类,ReentarntLock实现了Lock的接口 我们只需要使用这个,就可以不用使用synchronized同步关键字以及对应的notify ...

  8. Java多线程-----实现生产者消费者模式的几种方式

       1 生产者消费者模式概述 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理 ...

  9. java设计模式之生产者/消费者模式

    什么是生产者/消费者模式? 某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.线程.进程等).产生数据的模块,就形象地称为生产者:而处理数据的模块,就称为消费者 ...

随机推荐

  1. Java异常之RuntimeException

    人生不如意十有八九.在打Core Java里面的例子的时候总是一遍就过,但是实际上只要是自己想着动手去打造自己想要的东西,异常的状况也是十有八九的. 在Java中会使用异常处理的错误捕获机制处理这些异 ...

  2. C#基于联通短信Sgip协议构建短信网关程序

    此软件基于中国联通Sgip协议程序接口,适合在中国联通申请了短信发送端口的公司使用.短信群发已经成为现在软件系统.网络营销等必不可少的应用工具.可应用在短信验证.信息群发.游戏虚拟商品购买.事件提醒. ...

  3. windows系统下的两个批处理命令

    启动应用:***.exe 关闭应用:taskkill /f /im ***.exe 保存为.bat文件

  4. ajax $.post 一直报 Forbidden (CSRF token missing or incorrect.)

    由于后台整合类视图代码,所以修改了写法,完了之后用下面的写法写的post请求都报 403 error $.post( "{% url 'test_record:select_node_pag ...

  5. Ping 命令的执行过程和应用协议

    1. ICMP是“Internet Control Message Ptotocol”的缩写.它是TCP/IP协议族的一个子协议,用于在IP主机.路由器之间传递控制消息. 控制消息是指网络通不通.主机 ...

  6. VB6 代码编辑页面添加支持滚轮模式

    VB6 中的代码编辑页面默认是不支持滚轮模式的,这让在编辑代码时的体验很是不爽. 但在64位win10系统进行加载配置时,可能会出现问题,可用如下方法解决: http://download.micro ...

  7. 01Qt中的隐式共享

    隐式共享 ​ 隐式共享又称为回写复制(copy on write).当两个对象共享同一分数据时(通过浅拷贝实现数据共享),如果数据不改变,则不进行数据的复制.而当某个对象需要需要改变数据时,则进行深拷 ...

  8. destoon 自定义session丢失

    destoon 在使用session之前 应该实例化 $s​ession = new dsession(); destoon通过配置文件加载了不同session存储方式.如果你使用session的页面 ...

  9. python网络-Socket之TCP编程(26)

    一.TCP简介 1.TCP介绍 TCP协议,传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)是一种面向连接的.可靠的.基于字节流的传输层通信协议. TC ...

  10. manjaro中virtualbox(vbox)配置

    一.更新源的配置: 1).自动方法: 在 终端 执行下面的arch" style="color: #002be5">命令从官方的源列表中对中国源进行测速和设置 su ...