生产者消费者模型三种实现实例

生产者消费者模型,最少两个线程,一个生产资源,一个消费资源。 没有资源时,消费者线程需要挂起,等待生产者生产好了再去消费。 生产者生产过多,仓库放不下时,生产者线程需要挂起,等待消费者消费后,仓库腾出地方了再去生产。


就像包子店卖包子。生意火爆时,包子刚出笼就被抢光了,那后来的人在想买就要等待,等待老板再蒸包子,蒸好了再买。 生意不好的时候,蒸好的包子没人买,笼屉里面都是包子。老板想再蒸点包子也没地方放,只能等后来顾客来卖包子了,腾出来笼屉了,才能再蒸。


其中关键点在于,在相应的时间点挂起线程,在相应的时间点唤醒线程。

下面是三种方式的实现实例。

1、object的wait和notify实现生产者消费者

package designmode.productconsumermode.pcwithwaitandnotify;

// object的wait和notify实现生产者消费者
public class ProducerConsumerWithWaitNofity {
 public static void main(String[] args) {
 Resource resource = new Resource();
 //生产者线程
 ProducerThread p1 = new ProducerThread(resource);
 ProducerThread p2 = new ProducerThread(resource);
 ProducerThread p3 = new ProducerThread(resource);
 //消费者线程
 ConsumerThread c1 = new ConsumerThread(resource);
 //ConsumerThread c2 = new ConsumerThread(resource);
 //ConsumerThread c3 = new ConsumerThread(resource);

 p1.start();
 p2.start();
 p3.start();
 c1.start();
 //c2.start();
 //c3.start();
 }
}

/**
 * 公共资源类
 */
class Resource {//重要
 //当前资源数量
 private int num = 0;
 //资源池中允许存放的资源数目
 private int size = 1;

 /**
 * 从资源池中取走资源
 */
 public synchronized void remove() {
 if (num == size) {
 num--;
 System.out.println("消费者" + Thread.currentThread().getName() +
 "消耗一件资源," + "当前线程池有" + num + "个");
 notifyAll();//通知生产者生产资源
 } else {
 try {
 //如果没有资源,则消费者进入等待状态
 wait();
 System.out.println("消费者" + Thread.currentThread().getName() + "线程进入等待状态");
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
 }

 /**
 * 向资源池中添加资源
 */
 public synchronized void add() {
 if (num == 0) {
 num++;
 System.out.println(Thread.currentThread().getName() + "生产一件资源,当前资源池有"
 + num + "个");
 notifyAll(); // 通知消费者消费资源
 } else {
 //如果当前资源池中有10件资源
 try {
 wait();//生产者进入等待状态,并释放锁
 System.out.println(Thread.currentThread().getName() + "线程进入等待");
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
 }
}

/**
 * 消费者线程
 */
class ConsumerThread extends Thread {
 private Resource resource;

 public ConsumerThread(Resource resource) {
 this.resource = resource;
 }

 @Override
 public void run() {
 // 不断去消耗资源
 while (true) {
 try {
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 resource.remove();
 }
 }
}

/**
 * 生产者线程
 */
class ProducerThread extends Thread {
 private Resource resource;

 public ProducerThread(Resource resource) {
 this.resource = resource;
 }

 @Override
 public void run() {
 //不断地生产资源
 while (true) {
 try {
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 resource.add();
 }
 }
}

2、使用Condition、lock实现生产者消费者

package designmode.productconsumermode.pcwithlockcondition;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

// 使用Condition、lock实现生产者消费者
public class TestPCwithConditionLock {
 public static void main(String[] args) {
 Lock lock = new ReentrantLock();
 Condition proCd = lock.newCondition();
 Condition conCd = lock.newCondition();
 Resource resource = new Resource(lock, proCd, conCd);
 ProThread pro = new ProThread(resource);
 Thread con = new Thread(new ConThread(resource));
 Thread con1 = new Thread(new ConThread(resource));
 pro.start();
 con.start();
 con1.start();
 }
}

class ProThread extends Thread {
 private Resource resource;

 public ProThread(Resource resource) {
 this.resource = resource;
 }

 @Override
 public void run() {
 while (true) {
 try {
 sleep((long) (1000 * Math.random()));
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 resource.product();
 }
 }
}

class ConThread implements Runnable {
 private Resource resource;

 public ConThread(Resource resource) {
 this.resource = resource;
 }

 @Override
 public void run() {
 while (true) {
 try {
 Thread.sleep((long) (1000 * Math.random()));
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 resource.consumer();
 }
 }
}

class Resource {
 private int max = 10; // 资源池容量
 private int count = 0; // 当前资源数量
 private Lock lock;
 private Condition proCd;
 private Condition conCd;

 public Resource(Lock lock, Condition proCd, Condition conCd) {
 this.lock = lock;
 this.proCd = proCd;
 this.conCd = conCd;
 }

 public void product() {
 lock.lock();
 try {
 if (count < max) {
 count++;
 System.out.println("线程[" + Thread.currentThread().getName() + "]:正在生产,当前资源池容量为:" + count);
 conCd.signalAll();
 } else {
 proCd.await();
 System.out.println("资源池容量已满,停止生产,生产线程[" + Thread.currentThread().getName() + "}挂起");
 }
 } catch (InterruptedException e) {
 e.printStackTrace();
 } finally {
 lock.unlock();
 }
 }

 public void consumer() {
 lock.lock();
 try {
 if (count > 0) {
 count--;
 System.out.println("线程[" + Thread.currentThread().getName() + "]:正在消费,当前资源池容量为:" + count);
 proCd.signalAll();
 } else {
 conCd.await();
 System.out.println("资源池容量为0,无法消费,消费线程[" + Thread.currentThread().getName() + "}挂起");
 }
 } catch (InterruptedException e) {
 e.printStackTrace();
 } finally {
 lock.unlock();
 }
 }
}

3、阻塞队列BlockingQueue实现生产者消费者

package designmode.productconsumermode.pcwithblockingqueue;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

//使用阻塞队列BlockingQueue实现生产者消费者
public class BlockingQueueConsumerProducer {
 public static void main(String[] args) {
 Resource3 resource = new Resource3();
 //生产者线程
 ProducerThread3 p = new ProducerThread3(resource);
 //多个消费者
 ConsumerThread3 c1 = new ConsumerThread3(resource);
 ConsumerThread3 c2 = new ConsumerThread3(resource);

 p.start();
 c1.start();
 c2.start();
 }
}

/**
 * 消费者线程
 */
class ConsumerThread3 extends Thread {
 private Resource3 resource3;

 public ConsumerThread3(Resource3 resource) {
 this.resource3 = resource;
 }

 public void run() {
 while (true) {
 try {
 Thread.sleep((long) (1000 * Math.random()));
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 resource3.remove();
 }
 }
}

/**
 * 生产者线程
 */
class ProducerThread3 extends Thread {
 private Resource3 resource3;

 public ProducerThread3(Resource3 resource) {
 this.resource3 = resource;
 }

 public void run() {
 while (true) {
 try {
 Thread.sleep((long) (1000 * Math.random()));
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 resource3.add();
 }
 }
}

class Resource3 {
 private BlockingQueue resourceQueue = new LinkedBlockingQueue(10);

 /**
 * 向资源池中添加资源
 */
 public void add() {
 try {
 resourceQueue.put(1);
 System.out.println("生产者" + Thread.currentThread().getName()
 + "生产一件资源," + "当前资源池有" + resourceQueue.size() +
 "个资源");
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }

 /**
 * 向资源池中移除资源
 */
 public void remove() {
 try {
 resourceQueue.take();
 System.out.println("消费者" + Thread.currentThread().getName() +
 "消耗一件资源," + "当前资源池有" + resourceQueue.size()
 + "个资源");
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
}

运行下实例,再仿着写一下就理解了。

关于wait、notify线程基础知识不太熟悉的可以看这个:https://www.jianshu.com/p/2b56a169866c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值