Java 多线程同步生产者消费者问题-monitor

   对这个问题更深一点理解是,每一个线程都在竞争这个类的实例的monitor对象。

  java会为每个object对象分配一个monitor,当某个对象的同步方法(synchronized methods )被多个线程调用时,该对象的monitor将负责处理这些访问的并发独占要求。

  任何时刻,对一个指定object对象的某同步方法只能由一个线程来调用。java对象的monitor是跟随object实例来使用的,而不是跟随程序代码。两个线程可以同时执行相同的同步方法,比如:一个类的同步方法是xMethod(),有a,b两个对象实例,一个线程执行a.xMethod(),另一个线程执行b.xMethod(). 互不冲突。下面是单生产者单消费者的实例

  1 /*
  2  * 生产者消费者
  3  * 分类:
  4  * 单生产者单消费者
  5  * 多生产者的消费者
  6  * 
  7  * 
  8  * 单生产者单消费者:
  9  * 两个线程:生产线程,消费线程
 10  * 两个任务:生产任务,消费任务
 11  * 一份数据
 12  */
 13 public class Demo4 {
 14     public static void main(String[] args) {
 15         //1.准备数据
 16         Product product = new Product();
 17         //2.创建生产消费任务
 18         Producer producer = new Producer(product);
 19         Consumer consumer = new Consumer(product);
 20         //3.创建生产消费线程
 21         Thread thread1 = new Thread(producer);
 22         Thread thread2 = new Thread(consumer);
 23         //4.开启线程
 24         thread1.start();
 25         thread2.start();
 26     }
 27 }
 28 
 29 //数据类
 30 class Product{
 31     String name;
 32     double price;
 33     int count;
 34     
 35     //标识
 36     boolean flag;
 37     
 38     //准备生产
 39     public synchronized void setProduce(String name,double price) {
 40         if (flag == true) {
 41             try {
 42                 wait();
 43             } catch (InterruptedException e) {
 44                 // TODO Auto-generated catch block
 45                 e.printStackTrace();
 46             }
 47         }
 48         
 49         this.name = name;
 50         this.price = price;
 51         
 52         System.out.println(Thread.currentThread().getName()+"  生产了:"+name+"  产品的数量:"+count+"  产品的价格:"+price);
 53         
 54         count++;
 55         
 56         flag = !flag;
 57         
 58         //唤醒消费线程
 59         notify();
 60     }
 61     //准备消费
 62     public synchronized void consume() {
 63         if (flag == false) {
 64             try {
 65                 wait();
 66             } catch (InterruptedException e) {
 67                 // TODO Auto-generated catch block
 68                 e.printStackTrace();
 69             }
 70         }
 71         
 72         System.out.println(Thread.currentThread().getName()+"  消费了:"+name+"  产品的数量:"+count+"  产品的价格:"+price);
 73         
 74         flag = !flag;
 75         
 76         //唤醒生产线程
 77         notify();
 78     }
 79 }
 80 //生产任务
 81 class Producer implements Runnable{
 82     Product product;
 83 
 84     public Producer(Product product) {
 85         super();
 86         this.product = product;
 87     }
 88     
 89     public void run() {
 90         while (true) {
 91             product.setProduce("bingbing", 10);
 92         }
 93     }
 94 }
 95 //消费任务
 96 
 97 class Consumer implements Runnable{
 98     Product product;
 99 
100     public Consumer(Product product) {
101         super();
102         this.product = product;
103     }
104     
105     public void run() {
106         while (true) {
107             product.consume();
108         }
109     }
110 }
生产者消

  多生产者多消费者:
 * 两个生产线程,两个消费线程
 * 两个任务:生产任务,消费任务
 * 一份数据
 *
 * 生产任务与消费任务共用一个数据--产品类
 *
 * 要求:最终也要实现一次生产一次消费
 *
 *错误描述:当有两个生产线程,两个消费线程同时存在的时候,有可能出现生产一次,消费多次或者生产多次消费一次的情况.
 *原因:当线程被重新唤醒之后,没有判断标记,直接执行了下面的代码
 *
 *解决办法:将标记处的if改成while
 *
 *问题描述:继续运行程序,会出现死锁的情况(4个线程同时处于等待状态)
 *原因:唤醒的是本方的线程,最后导致所有的线程都处于等待状态.
 *
 *解决办法:将notify改成notifyAll.保证将对方的线程唤醒
 *
 *死锁:出现的情况有两种
 *1.所有的线程处于等待状态
 *2.锁之间进行嵌套调用
 *
 */

public class Demo5 {
    public static void main(String[] args) {
        //1.准备数据
        Product1 product = new Product1();
        //2.创建生产消费任务
        Producer1 producer = new Producer1(product);
        Consumer1 consumer = new Consumer1(product);
        //3.创建生产消费线程
        Thread thread0 = new Thread(producer);
        Thread thread1 = new Thread(producer);
        Thread thread2 = new Thread(consumer);
        Thread thread3 = new Thread(consumer);
        //4.开启线程
        thread0.start();
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

//数据类
class Product1{
    String name;
    double price;
    int count;
    
    //标识
    boolean flag;
    
    //准备生产
    public synchronized void setProduce(String name,double price) {
        while (flag == true) {
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        this.name = name;
        this.price = price;
        
        System.out.println(Thread.currentThread().getName()+"  生产了:"+name+"  产品的数量:"+count+"  产品的价格:"+price);
        
        count++;
        
        flag = !flag;
        
        //唤醒消费线程
        //notify();
        notifyAll();
    }
    //准备消费
    public synchronized void consume() {
        while (flag == false) {
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        System.out.println(Thread.currentThread().getName()+"  消费了:"+name+"  产品的数量:"+count+"  产品的价格:"+price);
        
        flag = !flag;
        
        //唤醒生产线程
        //notify();
        notifyAll();
    }
}
//生产任务
class Producer1 implements Runnable{
    Product1 product;

    public Producer1(Product1 product) {
        super();
        this.product = product;
    }
    
    public void run() {
        while (true) {
            product.setProduce("bingbing", 10);
        }
    }
}
//消费任务

class Consumer1 implements Runnable{
    Product1 product;

    public Consumer1(Product1 product) {
        super();
        this.product = product;
    }
    
    public void run() {
        while (true) {
            product.consume();
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/blogsyun/p/9483684.html