黑馬程序員_

--------------------ASP.Net+Android+IOS開發.Net培訓、期待與您交流! --------------------


1. 生產者和消費者

       1. 概述

          可以有多個消費者,也可以有多個生產者,他們可以一邊生產一邊消費。

 

         注意:

           不管是消費者還是生產者,在生產和消費的前提下,都要判斷一下。要用while()循環判斷,,如果用if()的話,有可能會發生連續生產或者連續消費,這樣就不是一對一了,喚醒的話,就繼續執行下面的語句,不再判斷的原因。

如果用while()進行判斷的話,就可以循環判斷,防止前面的情況發生,但是要用signalAll()或notifyAll(),這樣可以避免死鎖。要是用signal()或notify()的話,會產生死鎖。

      2.(Lock)

         1.5新特性:

         Lock和Condition對象。

         Lock替換了synchronized,以前鎖是看不見的,替換成Lock可以看見的。可以使用Lock(接口)子類對象進行管理鎖,lock()方法獲取鎖,unlock()方法釋放鎖。

         Condition替換了Object類中的wait(),notify(),notifyAll()方法。

         Condition對象通過鎖來獲取,newCondition()方法獲取。

          Conditioncondition=lock.newCondition()

        condition.await()替換了wait()

        condition.signal()替換了notify()

          condition.signalAll()替換了notifyAll()

  

   

              3.示例1

          這是使用的是一個鎖,一個Condition對象


importjava.util.concurrent.locks.Condition;
importjava.util.concurrent.locks.Lock;
importjava.util.concurrent.locks.ReentrantLock;
/*資源*/
public class Resource {
    private String name;
    private int count = 1;
    private boolean flag = false;
    private Lock lock = new ReentrantLock();//鎖
    private Condition condition = lock.newCondition();//獲取Condition對象
 
    /* 生產 */
    public void set(String name) throws InterruptedException {
         lock.lock();
         try {
               while (flag)
                    condition.await();//線程等待
               this.name = name + ":" + (count++);
               System.out.println(Thread.currentThread().getName() +"生產者生產:"
                          + this.name);
               this.flag = true;
               condition.signalAll();//喚醒線程所有
         } finally {
               lock.unlock();
         }
    }
 
    publicvoid show() throws InterruptedException {
         lock.lock();
         try{
               while(!flag)
                    condition.await();//線程等待
               System.out.println(Thread.currentThread().getName()+ "取出第"
                          +this.name );
               this.flag= false;
               condition.signalAll();//喚醒所有線程
         }finally {
               lock.unlock();
         }
    }
}
 
/*生產者*/
public class Produce implements Runnable {
  private Resource re = null;
 
  public Produce(Resource re) {
    this.re = re;
  }
 
  public void run() {
    while (true) {
      try {
 
         re.set("商品");
         Thread.sleep(10);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
    }
  }
 
}
/*消費者*/
public class Customer implements Runnable {
  private Resource re = null;
 
  public Customer(Resource re) {
    this.re = re;
  }
 
  public void run() {
    while (true) {
      try {
 
         re.show();
         Thread.sleep(10);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
    }
 
  }
 
}
/*測試類*/
public class Text {
  public static void main(String[] agrs) {
    Resource r = new Resource();
    new Thread(new Produce(r), "---生產者A----").start();
    new Thread(new Produce(r), "---生產者B----").start();
    new Thread(new Customer(r), "++消費者1++").start();
    new Thread(new Customer(r), "++消費者2++").start();
    new Thread(new Customer(r), "++消費者3++").start();
  }
}
 


結果:


---生產者A----生產者生產:商品:1

++消費者1++取出第商品:1

---生產者B----生產者生產:商品:2

++消費者3++取出第商品:2

---生產者B----生產者生產:商品:3

++消費者1++取出第商品:3

---生產者A----生產者生產:商品:4

++消費者2++取出第商品:4

---生產者A----生產者生產:商品:5

++消費者3++取出第商品:5

---生產者B----生產者生產:商品:6

++消費者2++取出第商品:6

---生產者A----生產者生產:商品:7

++消費者1++取出第商品:7

---生產者B----生產者生產:商品:8

++消費者2++取出第商品:8

---生產者A----生產者生產:商品:9

++消費者3++取出第商品:9

---生產者B----生產者生產:商品:10

++消費者2++取出第商品:10

---生產者A----生產者生產:商品:11

++消費者3++取出第商品:11

 

         4.示例2

                     使用的是一個鎖,多個Condition對象,不同的Condition對象喚醒的另一個Condition對象,這樣就可以不使用的signalAll()方法,

       思路:參生產者升生產出商品後,通知消費着(喚醒消費者),消費者消費商品後,通知生產者(喚醒生產者)

       只更改資源類就可以,其他的類不用更改。


     

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*資源*/
public class Resource {
    privateString name;
    privateint count = 1;
    privateboolean flag = false;
    privateLock lock = new ReentrantLock();//鎖
    privateCondition condition_pro = lock.newCondition();//獲取生產者的Condition對象
    privateCondition condition_cus = lock.newCondition();//獲取消費者Condition對象
 
    /* 生產 */
    publicvoid set(String name) throws InterruptedException {
         lock.lock();
         try{
               while(flag)
                    condition_pro.await();//線程等待(生產者不符合條件)
               this.name = name + ":" +(count++);
               System.out.println(Thread.currentThread().getName()+ "生產者生產:"
                          + this.name);
               this.flag= true;
               condition_cus.signal();//喚醒消費者
         }finally {
               lock.unlock();
         }
    }
 
    public voidshow() throws InterruptedException {
         lock.lock();
         try {
               while(!flag)
                    condition_cus.await();//線程等待 消費者,不符合條件
               System.out.println(Thread.currentThread().getName()+ "取出第"
                          +this.name );
               this.flag= false;
               condition_pro.signalAll();//喚醒生產者
         }finally {
               lock.unlock();
         }
    }
}

 

結果:

---生產者A----生產者生產:商品:1

++消費者1++取出第商品:1

---生產者B----生產者生產:商品:2

++消費者2++取出第商品:2

---生產者A----生產者生產:商品:3

++消費者3++取出第商品:3

---生產者B----生產者生產:商品:4

++消費者2++取出第商品:4

---生產者A----生產者生產:商品:5

++消費者1++取出第商品:5

---生產者B----生產者生產:商品:6

++消費者3++取出第商品:6

---生產者A----生產者生產:商品:7

++消費者1++取出第商品:7

---生產者B----生產者生產:商品:8

++消費者2++取出第商品:8

---生產者A----生產者生產:商品:9

++消費者1++取出第商品:9

---生產者B----生產者生產:商品:10

++消費者3++取出第商品:10

---生產者A----生產者生產:商品:11

++消費者2++取出第商品:11

---生產者B----生產者生產:商品:12

++消費者3++取出第商品:12

---生產者A----生產者生產:商品:13

++消費者3++取出第商品:13

---生產者B----生產者生產:商品:14

++消費者1++取出第商品:14

---生產者B----生產者生產:商品:15

++消費者3++取出第商品:15

---生產者A----生產者生產:商品:16

++消費者2++取出第商品:16

 


--------------------ASP.Net+Android+IOS開發.Net培訓、期待與您交流! --------------------


發佈了46 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章