Liver's Java
我不够贪心!其实我应该明白,心有多贪,舞台就会有多大!坚持!奋斗!
posts - 4,  comments - 6,  trackbacks - 0
昨天提到了线程,那么就不得不提到“生产者与消费者”这样一个经典的线程同步问题

场景描述:
    一个仓库,生产者在工厂里生产了产品后,将产品存放到仓库里,仓库存放数量有限,当满仓后,停止生产,直到有消费着将产品消费后才继续生产;消费者从仓库里提取产品,当仓库空仓时,停止消费产品,直到仓库中有产品时,才继续消费产品。

代码的实现(调整线程sleep时间可以实现生产速度与消费速度的不同):
TestProduceAndConsumer.java
package com.nantian;

import java.util.Random;

public class TestProduceAndConsumer {
    
public static void main(String[] args) {
        
// 创建一个工厂对象
        ProductFactory pf = new ProductFactory();
        
// 创建一个生产者和一个消费者,传递工厂的引用,保证两者操作的是同一个工厂
        Producer p = new Producer(pf);
        Consumer c 
= new Consumer(pf);
        
// 启动两个线程
        p.start();
        c.start();
    }

}


// 产品工厂
class ProductFactory {
    
// product表示仓库
    private char[] product = ' '' '' '' '' '};
    
// flag标记产品数量
    private int flag = 0;

    
// 生产产品
    public synchronized void produceProduct(char p) throws InterruptedException {
        
// 判断产品是否满仓,以便决定是否继续生产
        if (flag == product.length) {
            
this.wait();
        }

        
// 当代码执行到这里,一定不是满仓状态
        product[flag++= p;
        
// 查看此时仓库状态(这里不属于业务逻辑部分)
        System.out.print(p + "被生产,当前仓库状态:");
        
for (char tmp : product) {
            System.out.print(tmp);
        }

        System.out.println();
        
// 生产方法完成,如果存在等待队列中的线程,应该唤醒
        this.notifyAll();
    }

    
    
// 消费产品
    public synchronized char consumeProduct() throws InterruptedException {
        
// 判断仓库是否空仓,以便决定是否消费产品
        if(flag == 0{
            
this.wait();
        }

        
// 当代码执行到这里,一定不是空仓状态
        char p = product[--flag]; product[flag]=' ';
        
// 查看此时仓库状态(这里不属于业务逻辑部分)
        System.out.print(p + "被消费,当前仓库状态:");
        
for(char tmp : product) {
            System.out.print(tmp);
        }

        System.out.println();
        
// 消费方法完成,如果存在等待队列中的线程,应该唤醒
        this.notifyAll();
        
return p;
    }

}


// 生产者
class Producer extends Thread {
    
private ProductFactory pf = null;
    
    
public Producer(ProductFactory pf) {
        
this.pf = pf;
    }

    
    
public void run() {
        
// 一共生产20个产品
        for(int i=0; i<20; i++{
            
// 随机产生一个大写字母作为产品
            Random r = new Random();
            
char p = (char)(r.nextInt(26+ 'A');
            
try {
                
// 产品入库
                pf.produceProduct(p);
                
// 故意sleep,以便消费线程有机会获得CPU时间片,方便演示
                Thread.sleep(200);
            }
 catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }

}


// 消费者
class Consumer extends Thread {
    
private ProductFactory pf = null;
    
    
public Consumer(ProductFactory pf) {
        
this.pf = pf;
    }

    
    
public void run() {
        
// 一共消费20个产品
        for(int i=0; i<20; i++{
            
try {
                
// 产品出库
                pf.consumeProduct();
                
// 故意sleep,以便生产线程有机会获得CPU时间片,方便演示
                
// sleep时间稍微错开,阻止同时竞争CPU时间片
                Thread.sleep(300);
            }
 catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }

}
posted on 2009-06-04 10:57 Liver 阅读(1417) 评论(4)  编辑  收藏 所属分类: CoreJava

FeedBack:
# re: 再谈线程:生产者与消费者
2009-06-04 16:22 | wuzhongxing
利用jdk1.5的concurrent包里面的blockqueue,实现这种模式还是比较简单的  回复  更多评论
  
# re: 再谈线程:生产者与消费者
2009-06-04 18:10 | 乐蜂
实现这种模式还是比较简单的  回复  更多评论
  
# re: 再谈线程:生产者与消费者[未登录]
2009-06-06 16:57 | charlee
// 判断产品是否满仓,以便决定是否继续生产
if (flag == product.length) {
this.wait();
}

// 判断仓库是否空仓,以便决定是否消费产品
if(flag == 0) {
this.wait();
}

为什么要用if呢?你不觉得while更好么?  回复  更多评论
  
# re: 再谈线程:生产者与消费者
2009-06-15 15:53 | 分享爱的空间
言简意赅,不错。。。。
希望看到更加深入的。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 

<2009年6月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用链接

留言簿

随笔分类(5)

随笔档案(5)

搜索

  •  

最新评论

阅读排行榜

评论排行榜