自己一直对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实现非常不错了,一般选择这个就可以了。