现在的位置: 首页 > 综合 > 正文

黑马程序员_<<生产者和消费着>>

2018年09月16日 ⁄ 综合 ⁄ 共 4555字 ⁄ 字号 评论关闭

--------------------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培训、期待与您交流!
--------------------

抱歉!评论已关闭.