案例介绍:
    某工厂生产某种产品,有甲、乙销售员负责销售产品。每件产品都有自己的编号。

    工厂生产某种产品所需的时间单位为1,销售人员每3个时间单位销售2件商品,生产与销售的协调关系如下:
    当商品库存大于100件时工厂停止生产该商品,当产品库存小于5件时候停止销售,模拟该过程。

    1.创建工程

    2.使用notify和wait处理线程同步问题

    3.使用队列技术存放产品

    4.正确的使用锁

    5.能最终统计30时间单位内的销售冠军。

    设置生产者worker,仓库storage,消费者sell1与sell2,产品phone,测试类Test

    phone

    1. /**
    2. * 产品
    3. */
    4. public class Phone {
    5. //编号
    6. private int id;
    7. private String name;
    8. private static int no = 1;
    9. public Phone(String name) {
    10. this.id = no++;
    11. this.name = name;
    12. }
    13. public Phone() {
    14. this.id = no++;
    15. }
    16. public int getId() {
    17. return id;
    18. }
    19. public void setId(int id) {
    20. this.id = id;
    21. }
    22. public String getName() {
    23. return name;
    24. }
    25. public void setName(String name) {
    26. this.name = name;
    27. }
    28. public static int getNo() {
    29. return no;
    30. }
    31. public static void setNo(int no) {
    32. Phone.no = no;
    33. }
    34. @Override
    35. public String toString() {
    36. return "Phone{" +
    37. "id=" + id +
    38. ", name='" + name + '\'' +
    39. '}';
    40. }
    41. }

    worker

    1. /**
    2. * 生产者
    3. * @author
    4. */
    5. public class Worker extends Thread{
    6. private Storage storage;
    7. private Sell1 sell1;
    8. private Sell2 sell2;
    9. public Worker(Storage storage, Sell1 sell1, Sell2 sell2,String name) {
    10. super(name);
    11. this.storage = storage;
    12. this.sell1 = sell1;
    13. this.sell2 = sell2;
    14. }
    15. @Override
    16. public void run() {
    17. while(true){
    18. //调用生产的方法
    19. storage.in();
    20. try {
    21. //100ms为一个时间单位
    22. Thread.sleep(100);
    23. } catch (InterruptedException e) {
    24. e.printStackTrace();
    25. }
    26. //如果两个销售员线程都结束了,就结束生产者线程
    27. if(!this.sell1.isAlive() && !this.sell2.isAlive()){
    28. break;
    29. }
    30. }
    31. }
    32. }

    storage

    1. /**
    2. * 共享的仓库对象
    3. */
    4. public class Storage {
    5. /**
    6. * 队列进行入库处理
    7. */
    8. private LinkedList<Phone> linkedList;
    9. /**
    10. * 销售员1的产品计数
    11. */
    12. private int count1 = 0;
    13. /**
    14. * 销售员2的产品计数
    15. */
    16. private int count2 = 0;
    17. public LinkedList<Phone> getLinkedList() {
    18. return linkedList;
    19. }
    20. public int getCount1() {
    21. return count1;
    22. }
    23. public int getCount2() {
    24. return count2;
    25. }
    26. public Storage(LinkedList<Phone> linkedList) {
    27. this.linkedList = linkedList;
    28. }
    29. /**
    30. * 生产者调用的方法:入库
    31. */
    32. public synchronized void in(){
    33. if(this.getLinkedList().size()>100){
    34. try {
    35. //生产者线程进入等待池
    36. wait();
    37. } catch (InterruptedException e) {
    38. e.printStackTrace();
    39. }
    40. }else {
    41. Phone phone = new Phone("荣耀");
    42. //存入队列,先进先出,offer是入队方法
    43. linkedList.offer(phone);
    44. System.out.println(Thread.currentThread().getName()+"生产了"+phone.getName()+",产品编号为"+phone.getId()+"库存数量为"+this.getLinkedList().size());
    45. //如果库存大于五件,就可以唤醒消费者进行消费
    46. if(this.getLinkedList().size()>5){
    47. notifyAll();
    48. }
    49. }
    50. }
    51. /**
    52. * 消费者调用的方法:出库
    53. */
    54. public synchronized void out() {
    55. if (this.getLinkedList().size() < 5) {
    56. try {
    57. //消费者线程进入等待池
    58. wait();
    59. } catch (InterruptedException e) {
    60. e.printStackTrace();
    61. }
    62. }else{
    63. //对比字节码文件,判断是哪个销售员线程
    64. if(Thread.currentThread().getClass() == Sell1.class){
    65. count1++;
    66. }else {
    67. count2++;
    68. }
    69. //出队的方法
    70. Phone poll = linkedList.poll();
    71. System.out.println(Thread.currentThread().getName()+"出售了"+poll.getName()+",产品编号为"+poll.getId()+"库存数量为"+this.getLinkedList().size());
    72. //唤醒等待池的线程
    73. notifyAll();
    74. }
    75. }
    76. }

    sell1

    1. public class Sell1 extends Thread{
    2. private Storage storage;
    3. public Sell1(Storage storage,String name) {
    4. super(name);
    5. this.storage = storage;
    6. }
    7. @Override
    8. public void run() {
    9. for (int i = 1;i <= 10;i++){
    10. storage.out();
    11. storage.out();
    12. try {
    13. Thread.sleep(300);
    14. } catch (InterruptedException e) {
    15. e.printStackTrace();
    16. }
    17. }
    18. System.out.println(Thread.currentThread().getName()+"销售的产品数量为:"+storage.getCount1());
    19. }
    20. }

    sell2

    1. public class Sell2 extends Thread{
    2. private Storage storage;
    3. public Sell2(Storage storage,String name) {
    4. super(name);
    5. this.storage = storage;
    6. }
    7. @Override
    8. public void run() {
    9. for (int i = 1;i <= 10;i++){
    10. storage.out();
    11. storage.out();
    12. try {
    13. Thread.sleep(300);
    14. } catch (InterruptedException e) {
    15. e.printStackTrace();
    16. }
    17. }
    18. System.out.println(Thread.currentThread().getName()+"销售的产品数量为:"+storage.getCount2());
    19. }
    20. }

    Test

    1. public class Test {
    2. public static void main(String[] args) {
    3. //创建仓库对象
    4. Storage storage = new Storage(new LinkedList<Phone>());
    5. //创建销售员线程
    6. Sell1 sell1 = new Sell1(storage,"小崔");
    7. Sell2 sell2 = new Sell2(storage, "肥总");
    8. //创建生产者线程
    9. Worker worker = new Worker(storage, sell1, sell2, "集团");
    10. worker.start();
    11. sell1.start();
    12. sell2.start();
    13. //合并线程
    14. try {
    15. sell1.join();
    16. sell2.join();
    17. worker.join();
    18. } catch (InterruptedException e) {
    19. e.printStackTrace();
    20. }
    21. //在除主线程外所以线程执行完毕后再运行
    22. if(storage.getCount1() > storage.getCount2()){
    23. System.out.println("小崔是销售冠军!!!");
    24. }else {
    25. System.out.println("肥总是销售冠军!!!");
    26. }
    27. }
    28. }