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

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

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

以示例来说明问题:

以下程序参考至: 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关键字,对共享资源的锁定,以达到线程同步的效果。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值