生产者消费者代码_程序员:设计模式-生产者消费者分析以及实现的三种方式...

所谓生产者消费者模式,即N个线程进行生产,同时N个线程进行消费,两种角色通过内存缓冲区进行通信,

为什么要使用这种模式进行生产代码。

优点:

极大的解决了代码之间的耦合程度

解释:之前我们写的代码可能是这样的,有A和B 两个功能代码处理数据,B代码的执行必须要依赖于A代码才能执行完B的功能,即A耦合于B。显然这严重影响B代码的生产,而且如果产生错误的话,也不容易及时的排查。采用生产者消费者模式,A代码将处理好的数据交给缓存区,B代码直接从缓存区拿取数据进行处理,这样就把A与B的依赖关系给简介的消除了。

7c2f70789a1c6c8208a4b8c5aae8aad1.png

Object的wait() / notify()方法

public class consumer {

public static void main(String[] args) {

stock s = new stock();

Get get = new Get(s);

Put put = new Put(s);

Get get1 = new Get(s);

Put put1 = new Put(s);

//多个生产者和消费者对缓存区进行拿放数据

get.start();

put.start();

get1.start();

put1.start();

}

}

//缓存区

class stock{

private int maxnum=10;//最大的容量通知消费者

private int minnum=0;//最小的容量通知生产者

private String name;//定义仓库中存在的内容

private ArrayList contain = new ArrayList<>();//存储的列表

//向里面放入东西

public synchronized void putOne(String name){

while(contain.size()>maxnum){//如果仓库中的容量大于最大容量进行线程等待

try {

this.wait();//线程等待

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

this.name = name;

contain.add(name);

System.out.println("生产者生产了"+name+"消费者赶紧来消费"+Thread.currentThread().getName());

this.notifyAll();//唤起所有线程

}

public synchronized void getOne(){

while(contain.size()<=minnum){//如果仓库没有低于最低容量

try {

this.wait();//线程等待 等待生产者生产

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println("消费者消费了"+contain.get(0)+"生产者赶紧生产"+Thread.currentThread().getName());

contain.remove(0);

this.notifyAll();//唤起

}

}

//拿

class Get extends Thread{

private stock s;//缓存区

public Get(stock s) {

this.s = s;

}

@Override

public synchronized void run() {

while(true){

s.getOne();

}

}

}

//放

class Put extends Thread{

private stock s;//缓存区

public Put(stock s) {

this.s = s;

}

@Override

public synchronized void run() {

while(true){

s.putOne("mac");

}

}

}

使用Lock和Condition的await() / signal()方法

import java.util.Queue;

import java.util.concurrent.LinkedBlockingQueue;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

/**

* @auther sofency

* @date 2019/11/29 21:16

* @package 设计模式.lock

* 使用锁进行控制 lock

*/

public class lockTest {

public static void main(String[] args) {

Queue queue = new LinkedBlockingQueue<>(100);

Lock put = new ReentrantLock();//生产者的锁

Lock get = new ReentrantLock();//消费者的锁

Condition noFull=put.newCondition();

Condition noEmpty = get.newCondition();

new Thread(new producer(queue,"alice0",put,get,60,noFull,noEmpty)).start();

new Thread(new producer(queue,"alice1",put,get,60,noFull,noEmpty)).start();

new Thread(new producer(queue,"alice2",put,get,60,noFull,noEmpty)).start();

new Thread(new consumer(queue,"sophia0",put,get,0,noFull,noEmpty)).start();

new Thread(new consumer(queue,"sophia1",put,get,0,noFull,noEmpty)).start();

new Thread(new consumer(queue,"sophia2",put,get,0,noFull,noEmpty)).start();

}

}

//生产者

class producer extends Thread{

private Queue queue;//传进来的是带容量的对列

private String name;//线程的名字设置

private Lock put;//生产锁

private Lock get;//消费锁

private int maxSize;//最大容量

private Condition noFull;

private Condition noEmpty;

public producer(Queue queue, String name, Lock put, Lock get, int maxSize, Condition noFull, Condition noEmpty) {

this.queue = queue;

this.name = name;

this.put = put;

this.get = get;

this.maxSize = maxSize;

this.noFull = noFull;

this.noEmpty = noEmpty;

}

@Override

public void run() {

while(true){

put.lock();//上锁

while(queue.size()==maxSize){

try {

System.out.println("对列已满 通知消费者进行消费");

noFull.await();//等待

} catch (InterruptedException e) {

e.printStackTrace();

}

}

try {

Thread.sleep((int)Math.random()*1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

queue.add("mac");//添加物品

System.out.println(name+"向对列里面添加mac"+queue.size());

noFull.signalAll();//唤醒其他生产者

put.unlock();

if(queue.size()==maxSize){

get.lock();

noEmpty.signalAll();

get.unlock();

}

}

}

}

//消费者

class consumer extends Thread{

private Queue queue;//传进来的是带容量的对列

private String name;//线程的名字设置

private Lock put;//生产锁

private Lock get;//消费锁

private int minnum;//最大容量

private Condition noFull;

private Condition noEmpty;

public consumer(Queue queue, String name, Lock put, Lock get, int minnum, Condition noFull, Condition noEmpty) {

this.queue = queue;

this.name = name;

this.put = put;

this.get = get;

this.minnum = minnum;

this.noFull = noFull;

this.noEmpty = noEmpty;

}

@Override

public void run() {

while(true){

get.lock();//上锁

while(queue.size()==minnum){

try {

System.out.println("对列快空了 通知生产者进行生产");

noEmpty.await();//等待

} catch (InterruptedException e) {

e.printStackTrace();

}

}

try {

Thread.sleep((int)Math.random()*1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

queue.remove();//拿取第一个物品

System.out.println(name+"向对列里面消费了mac"+queue.size());

if(queue.size()>minnum){

noEmpty.signal();//唤醒其他的消费者

}

get.unlock();

if(queue.size()==minnum){

put.lock();

noFull.signalAll();

put.unlock();

}

}

}

}

使用BlockingQueue阻塞队列方法

它在底层的实现方法中就已经进行同步操作了,因此我们再用生产者和消费者进行操作的时候不用再进行同步的操作, 具体的代码如下。

注意

a. LinkedBlockingDeque类中的put方法根据容量进行自动阻塞, 即容量超了之后自动进行等待并通知消费者进行消费

b. LinkedBlockingDeque类中的take()方法根据容量进行自动阻塞, 即容量为0后自动进行等待并通知生产者进行生产

public class block {

public static void main(String[] args) {

LinkedBlockingDeque link = new LinkedBlockingDeque<>(8);//指明容量

new Get(link,"alice").start();

new Put(link,"sofency").start();

}

}

//消费者

class Get extends Thread{

private LinkedBlockingDeque blockingDeque;

private String name;//线程的名字

public Get(LinkedBlockingDeque blockingDeque, String name) {

this.blockingDeque = blockingDeque;

this.name = name;

}

@Override

public void run() {

while(true){

try {

String str = blockingDeque.take();//超过自动阻塞

System.out.println(name + "向对列里面拿了"+str);

Thread.sleep(new Random().nextInt(1000));

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

//生产者

class Put extends Thread{

private LinkedBlockingDeque blockingDeque;

private String name;//线程的名字

public Put(LinkedBlockingDeque blockingDeque, String name) {

this.blockingDeque = blockingDeque;

this.name = name;

}

@Override

public void run() {

while(true){

try {

blockingDeque.put("mac");//超过自动阻塞

System.out.println(name + "向对列里面添加了mac");

Thread.sleep(new Random().nextInt(1000));

}catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

效果如下

6b171e791061ea0221d9ef20852bc3ef.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值