Java实现生产者和消费者问题

来源:互联网 发布:决战武林进阶数据坐骑 编辑:程序博客网 时间:2024/05/17 06:13
关于生产者和消费者的问题模型这里就不再详细描述
这里首先要定义三个类来分别代表生产者和消费者以及要生产或消费的物品
Producer.java
Consumer.java
Product.java
我们简单这么实现,假设生产者生产饼干或饮料当生产者生产完毕后通知消费者进行消费,当消费者消费完之后就通知生产者继续进行生产
实现如下:

生产者Producer.java

public class Producer implements Runnable {public Product pro;public Producer(Product pro){this.pro = pro;}@Overridepublic void run() {// 生产者生产50次并控制让其在偶数次生产饼干,奇数次生产饮料for(int i = 0; i < 50; i ++){if(i % 2 == 0){pro.set("饼干");}else{pro.set("饮料");}}}}
消费者Consumer.java

public class Consumer implements Runnable {private Product pro;public Consumer(Product pro){this.pro = pro;}@Overridepublic void run() {// 消费者消费50次for(int i = 0; i < 50; i ++){pro.get();}}}
产品Product.java

public class Product {// 所生产的产品private String product;// 定义信号量,是否有产品,默认为空即trueprivate boolean isEmpty = true;public String getProduct() {return product;}public void setProduct(String product) {this.product = product;}// 生产public void produce(String product) {synchronized (this) {while (!isEmpty) {// 如果不为空,等待消费者消费try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.setProduct(product);System.out.println("生产者生产------>" + this.getProduct());isEmpty = false;this.notify();}}// 消费public void consume() {synchronized (this) {while (isEmpty) {// 如果为空,等待生产者生产try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("消费者消费------>" + this.getProduct());isEmpty = true;this.notify();}}}

使用main方法进行测试
Test.java

public class Test {public static void main(String[] args) {// 产品Product pro = new Product();// 定义一个生产者Producer producer = new Producer(pro);// 定义一个消费者Consumer consumer = new Consumer(pro);// 启动生产者线程new Thread(producer).start();// 启动消费者线程new Thread(consumer).start();}}

执行结果:
生产者生产------>饼干
消费者消费------>饼干
生产者生产------>饮料
消费者消费------>饮料
生产者生产------>饼干
消费者消费------>饼干
生产者生产------>饮料
消费者消费------>饮料
.....

即生产者每生产一次,就会通知消费者消费一次,消费者消费完之后,就会通知生产者继续生产
我这里采用的是一个生产者和一个消费者的情况,对于多个生产者和多个消费者的情况,其实就是多启动几个生产者和消费者线程,此外程序需要将唤醒线程的方法改为:notifyAll

这里需要注意的是wait()、notify()、notifyAll(),这三个方法属于Object 不属于 Thread,这三个方法必须由同步监视对象来调用,即调用wait、notify、notifyAll方法的对象必须是synchronized所监视的对象

在上面我们采用了synchronized来进行线程的同步实现了生产者和消费者问题,现在我们采用jdk1.5版本以上采用的同步锁进行一次实现,同步锁和synchronized的效果一样都能够实现线程的同步,同时其功能更加强大。现在我们就用同步锁的方式来实现一下生产这和消费者问题,与之前不同的是这里要解决的一个问题就是,线程之间的通信怎么进行处理,由于同步锁没有像synchronized一样存在对固定对象的监视,因此wait、notify、notifyAll都不能再使用了。这里同步锁提供了另外的可代替的方式,就是Condition,Condition通过Lock的对象的newCondition方法产生,可起到同步监视器的作用。简单的说:Lock代替了同步方法或同步代码块,Condition代替了同步监视器的功能

下面我们就将之前的实现进行一下修改:
生产者:Producer.java
消费者:Consumer.java
都不用变

Product.java修改如下

public class Product {// 产品private String product;// 定义信号量,是否有产品private boolean isEmpty = true;// 定义同步锁private final ReentrantLock lock = new ReentrantLock();// 获取Condition对象private final Condition condition = lock.newCondition();public String getProduct() {return product;}public void setProduct(String product) {this.product = product;}// 生产public void produce(String product) {lock.lock();try {while (!isEmpty) {// 等待消费者消费condition.await();}this.setProduct(product);System.out.println("生产者生产------>" + this.getProduct());isEmpty = false;condition.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}// 消费public void consume() {lock.lock();try {while (isEmpty) {// 等待生产者生产condition.await();}System.out.println("消费者消费------>" + this.getProduct());isEmpty = true;condition.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}}

使用main方法测试和之前的结果一致

原创粉丝点击