JAVA 生产者与消费者模式

xiaoxiao2021-02-28  134

自己一直对Java多线程似是而非,刚好最近项目上线,时间相对比较空闲,重新温习了一遍多线程。参考书是<<疯狂java讲义>>。

以下自己动手写了一个生产者和消费者模式的代码。一共用了两种方法(synchronized 和 BlockingQueue)。Lock暂时没写。

一、synchronized 实现方法

1.先定义一个货物的实体Goods,用于生产者和消费者使用

package com.deshengzheng.thread.producer.notify; public class Goods { private String name; private String id; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } } 2.定义一个仓库Storge,用于存放和获取货物Goods

package com.deshengzheng.thread.producer.notify; import java.util.LinkedList; public class Storge { private static final int MAX_VALUE = 10; private LinkedList<Goods> list = new LinkedList<Goods>(); public void put() { synchronized (list) { try { while (list.size() == MAX_VALUE) { System.out.println(Thread.currentThread().getName() + ":仓库已满,请暂停生产"); list.wait(); } Goods goods = new Goods(); goods.setId(String.valueOf(Math.random())); goods.setName(Thread.currentThread().getName() + ":洗衣液"); if (list.add(goods)) { System.out.println(Thread.currentThread().getName() + "添加了一个产品"); //在windows上添加这句代码,运行正常,但是在mac上添加这条代码,会出现 //必须等待生产者生产完之后,消费者才可以去取,一直没明白,Java不是跨平台吗? //之后把这个睡眠添加在生产者线程的run方法里 //Thread.sleep((long) 300); list.notifyAll(); } } catch (Exception e) { e.printStackTrace(); } } } public void take() { synchronized (list) { try { while(list.size() == 0) { System.out.println(Thread.currentThread().getName() + ":仓库为空,请等待上架"); list.wait(); } list.removeLast(); System.out.println(Thread.currentThread().getName() + "取了一个产品"); //在windows上添加这句代码,运行正常,但是在mac上添加这条代码,会出现 //必须等待生产者生产完之后,消费者才可以去取,一直没明白,Java不是跨平台吗? //之后把这个睡眠添加在生产者线程的run方法里 //Thread.sleep( 300); list.notifyAll(); } catch (Exception e) { e.printStackTrace(); } } } }

3.有了仓库了,定义生产者来生产、消费者来消费

生产者

package com.deshengzheng.thread.producer.notify; /** * 生产者生产线程 * @ClassName:Producer * @Description: * @Author:zhengdesheng * @Date:2017年7月10日下午5:03:51 * @version:1.0.0 */ public class Producer extends Thread{ private Storge storge; public Producer(String name,Storge storge){ super(name); this.storge = storge; } @Override public void run() { for (int i = 0; i < 10; i++) { storge.put(); try { Thread.sleep((long) 300); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }

消费者

package com.deshengzheng.thread.producer.notify; /** * 消费者消费线程 * @ClassName:Consumer * @Description: * @Author:zhengdesheng * @Date:2017年7月10日下午5:04:38 * @version:1.0.0 */ public class Consumer extends Thread{ private Storge storge; public Consumer(String name,Storge storge){ super(name); this.storge = storge; } @Override public void run() { for (int i = 0; i < 10; i++) { storge.take(); try { Thread.sleep((long) 300); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } 4.测试类

package com.deshengzheng.thread.producer.notify; public class Test { public static void main(String[] args) { Storge storge = new Storge(); new Consumer("李晓明", storge).start();; new Producer("富士康", storge).start(); Thread t1 = new Producer("长虹", storge); // t1.setPriority(Thread.MIN_PRIORITY); t1.start(); Thread t = new Consumer("乔布斯", storge); //t.setPriority(Thread.MAX_PRIORITY); t.start(); } }

输出结果:

二、队列实现

队列实现区别只是在仓库类里面,所以这个地方只把仓库类贴出来,其他一模一样。

package com.deshengzheng.thread.producer.queue; import java.util.LinkedList; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import com.deshengzheng.thread.producer.notify.Goods; public class Storge { private static final int MAX_VALUE = 10; private BlockingQueue<Goods> list = new LinkedBlockingQueue<Goods>(MAX_VALUE); public void put() { Goods goods = new Goods(); goods.setId(String.valueOf(Math.random()*10)); goods.setName("洗衣液:"+goods.getId()); try { list.put(goods); System.out.println(Thread.currentThread().getName()+"添加了一个产品:"+goods.getName()); } catch (InterruptedException e) { e.printStackTrace(); } } public void take() { try { Goods goods = list.take(); System.out.println(Thread.currentThread().getName()+"取出一个产品:"+goods.getName()); } catch (InterruptedException e) { e.printStackTrace(); } } }

打印结果也是正确的。

两种方式都实现了消费者和生产者的功能。java本身的BlockingQueue实现非常不错了,一般选择这个就可以了。

转载请注明原文地址: https://www.6miu.com/read-33936.html

最新回复(0)