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();
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM