案例介绍:
某工厂生产某种产品,有甲、乙销售员负责销售产品。每件产品都有自己的编号。
工厂生产某种产品所需的时间单位为1,销售人员每3个时间单位销售2件商品,生产与销售的协调关系如下:
当商品库存大于100件时工厂停止生产该商品,当产品库存小于5件时候停止销售,模拟该过程。
1.创建工程
2.使用notify和wait处理线程同步问题
3.使用队列技术存放产品
4.正确的使用锁
5.能最终统计30时间单位内的销售冠军。
设置生产者worker,仓库storage,消费者sell1与sell2,产品phone,测试类Test
phone
/*** 产品*/public class Phone {//编号private int id;private String name;private static int no = 1;public Phone(String name) {this.id = no++;this.name = name;}public Phone() {this.id = no++;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public static int getNo() {return no;}public static void setNo(int no) {Phone.no = no;}@Overridepublic String toString() {return "Phone{" +"id=" + id +", name='" + name + '\'' +'}';}}
worker
/*** 生产者* @author*/public class Worker extends Thread{private Storage storage;private Sell1 sell1;private Sell2 sell2;public Worker(Storage storage, Sell1 sell1, Sell2 sell2,String name) {super(name);this.storage = storage;this.sell1 = sell1;this.sell2 = sell2;}@Overridepublic void run() {while(true){//调用生产的方法storage.in();try {//100ms为一个时间单位Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}//如果两个销售员线程都结束了,就结束生产者线程if(!this.sell1.isAlive() && !this.sell2.isAlive()){break;}}}}
storage
/*** 共享的仓库对象*/public class Storage {/*** 队列进行入库处理*/private LinkedList<Phone> linkedList;/*** 销售员1的产品计数*/private int count1 = 0;/*** 销售员2的产品计数*/private int count2 = 0;public LinkedList<Phone> getLinkedList() {return linkedList;}public int getCount1() {return count1;}public int getCount2() {return count2;}public Storage(LinkedList<Phone> linkedList) {this.linkedList = linkedList;}/*** 生产者调用的方法:入库*/public synchronized void in(){if(this.getLinkedList().size()>100){try {//生产者线程进入等待池wait();} catch (InterruptedException e) {e.printStackTrace();}}else {Phone phone = new Phone("荣耀");//存入队列,先进先出,offer是入队方法linkedList.offer(phone);System.out.println(Thread.currentThread().getName()+"生产了"+phone.getName()+",产品编号为"+phone.getId()+"库存数量为"+this.getLinkedList().size());//如果库存大于五件,就可以唤醒消费者进行消费if(this.getLinkedList().size()>5){notifyAll();}}}/*** 消费者调用的方法:出库*/public synchronized void out() {if (this.getLinkedList().size() < 5) {try {//消费者线程进入等待池wait();} catch (InterruptedException e) {e.printStackTrace();}}else{//对比字节码文件,判断是哪个销售员线程if(Thread.currentThread().getClass() == Sell1.class){count1++;}else {count2++;}//出队的方法Phone poll = linkedList.poll();System.out.println(Thread.currentThread().getName()+"出售了"+poll.getName()+",产品编号为"+poll.getId()+"库存数量为"+this.getLinkedList().size());//唤醒等待池的线程notifyAll();}}}
sell1
public class Sell1 extends Thread{private Storage storage;public Sell1(Storage storage,String name) {super(name);this.storage = storage;}@Overridepublic void run() {for (int i = 1;i <= 10;i++){storage.out();storage.out();try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+"销售的产品数量为:"+storage.getCount1());}}
sell2
public class Sell2 extends Thread{private Storage storage;public Sell2(Storage storage,String name) {super(name);this.storage = storage;}@Overridepublic void run() {for (int i = 1;i <= 10;i++){storage.out();storage.out();try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+"销售的产品数量为:"+storage.getCount2());}}
Test
public class Test {public static void main(String[] args) {//创建仓库对象Storage storage = new Storage(new LinkedList<Phone>());//创建销售员线程Sell1 sell1 = new Sell1(storage,"小崔");Sell2 sell2 = new Sell2(storage, "肥总");//创建生产者线程Worker worker = new Worker(storage, sell1, sell2, "集团");worker.start();sell1.start();sell2.start();//合并线程try {sell1.join();sell2.join();worker.join();} catch (InterruptedException e) {e.printStackTrace();}//在除主线程外所以线程执行完毕后再运行if(storage.getCount1() > storage.getCount2()){System.out.println("小崔是销售冠军!!!");}else {System.out.println("肥总是销售冠军!!!");}}}
