线程安全-生产者消费者demo

 

* 生产消费线程同步演示
* 同步方式:使用synchronized代码块作为同步机制实现同步与互斥,用等待唤醒作为线程通信方式,
* 使用库存len作为线程共享(同步)变量
* 生产和消防线程本身并不相关,商品仓库才是他们的共享资源(临界区),  使用生产消费的同步关键就是对仓库数据操作的同步,同一时间只允许一个线程进入.
* 注意事项:
* 信号量或同步参数的设置 (至关重要)。设置不当会同步失败,或死锁
* 调用并进入临界区操作后,离开时一定要释放资源并唤醒其他线程(notify 或 V操作)
* 相当于调用完同步代码后一定要调用notify唤醒操作,当有多个线程是要使用 notifyAll
* 临界区的共享变量,每一次进入都需要重新检查.

示例代码:

  1 public class Demo {
  2 
  3     /**
  4      * @param args
  5      */
  6     public static void main(String[] args) {
  7         // TODO Auto-generated method stub
  8         new Thread(new Production()).start();
  9         new Thread(new Consumption()).start();
 10 
 11     }
 12 
 13 }
 14 //Production consumption warehouse
 15 //
 16 /**
 17  * 
 18  * @ClassName: Warehouse 
 19  * @Description: TODO 仓库
 20  * @author: zw
 21  * @date: 2018年3月27日 下午1:26:49
 22  */
 23 class Warehouse{
 24     //库存数量,也用来指示 array下标
 25     private int len = -1;  //共享变量
 26     //仓库
 27     private int[] array = new int[10];  //共享变量
 28 
 29     private static Warehouse  wh = new Warehouse();
 30 
 31     //单例,  一个仓库
 32     private Warehouse(){}
 33     public static Warehouse getWarehouse(){
 34         return wh;
 35     }
 36 
 37 
 38     /**
 39      * 
 40      * @Title: out  
 41      * @Description: TODO 出仓<br> 如果没有库存就叫醒(notify)生产线程制造商品,然后wait.如果有库存,就拿走一件并且库存减1
 42      * @param @return
 43      * @param @throws InterruptedException   
 44      * @return int    仓库里的商品编号 
 45      * @throws
 46      */
 47     public int out() throws InterruptedException   {
 48         synchronized(this){
 49             while(this.len < 0){
 50                 //没有库存
 51                 this.notify();
 52                 this.wait();
 53             }
 54 
 55             return array[len--];
 56 
 57         }
 58     }
 59 
 60     //
 61     /**
 62      * @Title: in  
 63      * @Description: TODO 商品入仓<br> len < array.length-1 就表示仓库未满,则入仓并唤醒 消费者 ,如果仓库满就 wait
 64      * @param @param len 商品编号
 65      * @param @throws InterruptedException    设定文件  
 66      * @return void    返回类型  
 67      * @throws
 68      */
 69     public void in(int pid) throws InterruptedException {
 70         synchronized(this){
 71             while(this.len >= array.length-1){
 72                 this.wait();
 73             }
 74             array[++len] = pid;    
 75             this.notify();
 76         }
 77 
 78     }
 79 
 80 
 81 }
 82 
 83 /**
 84  * 
 85  * @ClassName: Production 
 86  * @Description: TODO 生产者
 87  * @author: zw
 88  * @date: 2018年3月27日 下午12:10:50
 89  */
 90 class Production implements Runnable{
 91     Warehouse arr = Warehouse.getWarehouse();
 92     public void run(){
 93         for(int i = 0; i < 100; i++){
 94             try {
 95                 //第i号产品入仓
 96                 arr.in(i);
 97             } catch (InterruptedException e) {
 98                 // TODO Auto-generated catch block
 99                 e.printStackTrace();
100             }
101             System.out.println("made:....."+i);
102         }
103     }
104 }
105 
106 
107 /**
108  * 
109  * @ClassName: Consumption 
110  * @Description: TODO 消费者
111  * @author: zw
112  * @date: 2018年3月27日 下午12:12:18
113  */
114 class Consumption implements Runnable{
115     Warehouse arr = Warehouse.getWarehouse();
116 
117     public void run(){
118         int pid = -1;
119         for(int i = 0; i < 100; i++){
120             try {
121                 pid = arr.out();
122             } catch (InterruptedException e) {
123                 // TODO Auto-generated catch block
124                 e.printStackTrace();
125             }        
126             System.out.println(i+"consumption:--"+pid);
127 
128         }
129     }
130 }

 

posted @ 2018-03-27 13:32  zhangwang010  阅读(302)  评论(0)    收藏  举报