Java多线程之生产者与消费者

1、仓库

 1 package com.cn.donleo.thread.house;
 2 
 3 /**
 4  * @author liangd
 5  * date 2020-11-02 10:36
 6  * code 仓库
 7  */
 8 public class StoreHouse {
 9     /**
10      * 仓库容纳数量
11      */
12     public static int count = 10;
13     /**
14      * 判断仓库是否有东西
15      */
16     public static Boolean isNull =false;
17     public static final Object OBJECT = new Object();
18 }

 

2、生产者

 1 package com.cn.donleo.thread.house;
 2 
 3 /**
 4  * @author liangd
 5  * date 2020-11-02 10:40
 6  * code
 7  */
 8 public class Productor extends Thread {
 9     /**
10      * 对于生产者来说,我们需要以下几个步骤:
11      * 判断生产者是否还可以生产,因为规定一天只生产10个,可以则继续,不能则返回
12      * 第一:判断仓库里面是否有还有物品
13      * 第二:如果有,则线程等待,即等待消费者来拿
14      * 第三:如果没有,则生产物品,并提示仓库里面有东西,并呼叫消费者
15      * 生产者的run方法,一直向仓库添加元素
16      */
17     @Override
18     public void run() {
19         while (true) {
20             //必须要求我们生产者和消费者里面的东西唯一,否则消费者拿到的东西就不是生产者生产的东西,
21             //所以不能用new WareHouse(),来创建对象
22             synchronized (StoreHouse.OBJECT) {
23                 if (StoreHouse.count == 0) {
24                     break;
25                 } else {
26                     if (!StoreHouse.isNull) {
27                         System.out.println(getName() + "生产者生产产品");
28                         StoreHouse.isNull = true;
29                         /*
30                            一、notify和notifyAll的区别
31                               主要区别:notify和notifyAll之间的关键区别在于notify()只会唤醒一个线程,
32                               而notifyAll方法将唤醒所有线程。
33 
34                            二、何时在Java中使用notify和notifyAll?
35                              1、如果所有线程都在等待相同的条件,并且一次只有一个线程可以从条件变为true,
36                                 则可以使用notify over notifyAll。
37                              2、在这种情况下,notify是优于notifyAll 因为唤醒所有这些因为我们知道只有一个线程会受益
38                                 而所有其他线程将再次等待,所以调用notifyAll方法只是浪费CPU。
39                              3、虽然这看起来很合理,但仍有一个警告,即无意中的接收者吞下了关键通知。
40                                 通过使用notifyAll,我们确保所有收件人都会收到通知
41 
42                          */
43                         StoreHouse.OBJECT.notifyAll();
44                     } else {
45                         try {
46                             /*
47                                一、notify、 notifyAll、wait属于Object里面的方法
48                                二、sleep和wait有什么区别
49                                  1、Sleep是属于Thread类的静态方法,wait属于Object的方法。
50                                  2、最主要是sleep方法没有释放锁,而是放弃CPU的调度。而wait方法释放了锁,
51                                     使得其他线程可以进入同步控制块或者方法。
52                                  3、wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,
53                                     而sleep可以在任何地方使用,synchronized(x){x.notify()//或者wait()}
54                                  4、sleep必须捕获异常,wait也需要捕获异常,notify和notifyAll不需要捕获异常
55                                  5、使用wait,notify可以达到线程之间的通信目的
56                             */
57                             /*
58                               1.使用sleep方法,在毫秒值结束后,线程睡醒进入到Runnable/blocked状态
59                               2.使用wait方法,wait方法如果在毫秒值结束后,还没有被notify唤醒,就会自动醒来,
60                                 线程睡醒进入到Runnable/blocked状态
61                              */
62                             StoreHouse.OBJECT.wait();
63 //                            StoreHouse.OBJECT.wait(500);
64                         } catch (InterruptedException e) {
65                             e.printStackTrace();
66                         }
67                     }
68                 }
69             }
70         }
71     }
72 }

 

3、消费者

 1 package com.cn.donleo.thread.house;
 2 
 3 /**
 4  * @author liangd
 5  * date 2020-11-02 10:40
 6  * code
 7  */
 8 public class Consumer extends Thread {
 9     /**
10      * 1.while(true)
11      * 2.synchronized ()
12      * 3.判断生产者是否已经停止生产了,如果已经停止了,就跳出,如果没有,则可以继续去仓库拿
13      * 4.判断仓库是否有物品,如果有,则直接拿。拿了就需要讲次数减一,然后呼叫生产者生产
14      * 5.如果没有,则等待生产者生产
15      */
16     @Override
17     public void run() {
18         while (true) {
19             //必须要求我们生产者和消费者里面的东西唯一,否则消费者拿到的东西就不是生产者生产的东西,
20             //所以不能用new WareHouse(),来创建对象
21             synchronized (StoreHouse.OBJECT) {
22                 try {
23                     //休眠0.5s
24                     Thread.sleep(500);
25                 } catch (InterruptedException e) {
26                     e.printStackTrace();
27                 }
28                 if (StoreHouse.count == 0) {
29                     break;
30                 } else {
31                     if (StoreHouse.isNull) {
32                         System.out.println(getName() + "消费者可以拿产品了");
33                         StoreHouse.isNull = false;
34                         StoreHouse.OBJECT.notifyAll();
35                         StoreHouse.count--;
36                     } else {
37                         try {
38                             StoreHouse.OBJECT.wait();
39                         } catch (InterruptedException e) {
40                             e.printStackTrace();
41                         }
42                     }
43                 }
44             }
45         }
46     }
47 }

 

4、测试类

 1 package com.cn.donleo.thread.house;
 2 
 3 /**
 4  * @author liangd
 5  * date 2020-11-02 10:56
 6  * code 生产者消费者测试类
 7  */
 8 public class TestProductorCunsumer {
 9     public static void main(String[] args){
10         //线程1
11         Productor productor = new Productor();
12         productor.setName("生产者");
13         //线程2
14         Consumer consumer1 = new Consumer();
15         consumer1.setName("A消费者");
16         //线程3
17         Consumer consumer2 = new Consumer();
18         consumer2.setName("B消费者");
19         productor.start();
20         consumer1.start();
21         consumer2.start();
22     }
23 }

 

posted @ 2020-12-01 18:23  donleo123  阅读(172)  评论(0编辑  收藏  举报