线程同步–生产者与消费者模式

来源:互联网 发布:对焦算法 编辑:程序博客网 时间:2024/05/23 16:21

生产者与消费者模式简单介绍:

生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来

以示例来说明问题:

以下程序参考至: http://www.iteye.com/topic/256991

首先是产品类:

Java代码 收藏代码

package consumerandproducter;  /**  * 单纯的产品类  * @author google  *  */  public class Product {      private int productId=0;      public Product(int id){          this.productId=id;      }      public int getProductId() {          return productId;      }      public String toString(){          return "product "+productId;      }  }  

再是仓库(缓冲区):

Java代码 收藏代码

package consumerandproducter;  /**  * 模拟缓冲区,以栈为数据结构,先进后出  * @author google  *  */  public class StoreHouse {      private int base=0;      private int top=0;      private Product[] products=new Product[10];      /**      * 入栈      * @param product      */      public synchronized  void push (Product product) {          while(top==products.length){              //当前的线程已经放弃对资源的占有,唤醒已经被wait的线程,唤醒的线程由JVM决定,不按优先级确定              notify();              try {                  System.out.println("仓库已满,正在等待消费……");                  wait();//此线程处于等待状态              } catch (Exception e) {                  e.printStackTrace();              }          }          products[top]=product;          top++;      }      /**      * 出栈      * @return      */      public synchronized Product pop(){          Product product=null;          while(top==base){              notify();              try {                  System.out.println("仓库已空,正在等待生产……");                  wait();              } catch (Exception e) {                  e.printStackTrace();              }          }          top--;          product=products[top];          products[top]=null;          return product;      }  }  

接着是消费者:

Java代码 收藏代码

package consumerandproducter;  public class Consumer implements Runnable {      private String consumerName;      //保留有缓冲区对象的引用,以便消费产品      private StoreHouse storeHouse;      public Consumer(String consumerName, StoreHouse storeHouse) {          this.consumerName = consumerName;          this.storeHouse = storeHouse;      }      public void run() {          while(true){              System.out.println("消费者"+consumerName+"已经消费"+storeHouse.pop());              try {                  Thread.sleep(2000);              } catch (InterruptedException e) {                  e.printStackTrace();              }          }      }      public String getConsumerName() {          return consumerName;      }      public void setConsumerName(String consumerName) {          this.consumerName = consumerName;      }  }  

然后是生产者:

Java代码 收藏代码

package consumerandproducter;  /**  * 生产者类  * @author google  *   */  public class Producter implements Runnable {      private String producterName;      //  保留有缓冲区对象的引用,以便将生产的产品放入缓冲区      private StoreHouse storeHouse;      public Producter(String producterName, StoreHouse storeHouse) {          this.producterName = producterName;          this.storeHouse = storeHouse;      }      public String getProducterName() {          return producterName;      }      public void setProducterName(String producterName) {          this.producterName = producterName;      }      public void producterProduct(){          //生产产品,并放入到仓库中          int i=0;          while(true){              i++;              Product product=new Product(i);              storeHouse.push(product);              System.out.println(producterName+"生产了");              try {                  Thread.sleep(2000);              } catch (InterruptedException e) {                  return;              }          }      }      public void run() {          producterProduct();      }  }  

测试类:

Java代码 收藏代码

package consumerandproducter;  import sun.security.krb5.internal.crypto.t;  public class Test {      public static void main(String[] args) {          StoreHouse storeHouse=new StoreHouse();          Producter producter=new Producter("生产者",storeHouse);          Consumer consumer=new Consumer("消费者",storeHouse);          Thread t1=new Thread(producter);          Thread t2=new Thread(consumer);          t1.start();          t2.start();          /**          * ~输出(随机抽取输出,每次测试的结果可能都有稍许不同):          *                  生产者生产了                 消费者消费者已经消费product 1                 生产者生产了                 消费者消费者已经消费product 2                 生产者生产了                 消费者消费者已经消费product 3                 生产者生产了                 消费者消费者已经消费product 4                 ...........                 仓库已空,正在等待生产……                 生产者生产了                 生产者生产了                 生产者生产了                 生产者生产了                 .........                 仓库已满,正在等待消费……             消费者消费者已经消费product 14             消费者消费者已经消费product 13             消费者消费者已经消费product 12             消费者消费者已经消费product 11             消费者消费者已经消费product 10                 ......          */      }  }  

小结:

此问题主要是考察java间多线程通信与资源同步, 其中主要是对于notify与wait方法的使用上,还有对于线程间资源的共享,利用synchronized关键字,对共享资源的锁定,以达到线程同步的效果。
原创粉丝点击