`
zl378837964
  • 浏览: 187275 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

生产者消费者问题 Thread

    博客分类:
  • java
阅读更多
    前段时间又回头看了看java基础的线程问题,感觉就是不一样;
容易得多,当初第一次真的搞晕人;
     顺便试了一下,多生产者消费者的同步通信问题:
              由生产者,消费者,仓库 三部分组成Product的处理
贴出来,交流一下。


package package com.pdsu.zhang.thread;

import java.util.LinkedList;
import java.util.Queue;
	
class Product {						 //	产品
	private int ID;
	private String name;
	
	public Product(int id, String name) {
		ID = id;
		this.name = name;
	}
	@Override
	public String toString() {
		return  "["+ID+"--"+name+"]";	
	}	
}
class Store {							//	仓库
	private final int MAX=10;
	private int flag=-1;
	Queue<Product> list =new LinkedList<Product>();// 队列
	private int id=0;
	Product temp;
	synchronized void add(){
		if(judge()==1){
			System.out.println("生产者 "+Thread.currentThread().getName()+" :仓库已满,请稍后生产.....");
			try {
				this.wait();
				//Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}else{
			temp=new Product(++id,"产品");
			if(judge()==-1){
				list.offer(temp);	
				this.notify();
			}else
				list.offer(temp);	
			System.out.println(Thread.currentThread().getName()+" 生产入仓库:"+temp.toString());	
			//  不放在run{}中,否则会:先打印消费后生产!  因为print和add没有被同步;
			try {	//  等会儿再生产,模拟生产耗时
				Thread.sleep(200);
			} catch (InterruptedException e) {e.printStackTrace();}
		}
	}
	synchronized void get(){
		if(judge()==-1){
			System.out.println("消费者 "+Thread.currentThread().getName()+" :仓库无货,请稍后再来.....");
			try {
				this.wait();
				//Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}else{
			if(judge()==1){
				temp = list.poll();
				this.notify();		// 不通知就会死等,死锁了
			}else
				temp = list.poll();	
			System.out.println(Thread.currentThread().getName()+" 消费了产品:"+temp.toString());	//    不放在run{}中,同上:
			try {	//  等会儿再消费,模拟消费耗时
				Thread.sleep(200);
			} catch (InterruptedException e) {e.printStackTrace();}
		}	
	}
		// 判断仓库的库存量
	synchronized int judge(){
		if(list.size()>=MAX)
			 flag=1;
		else if(list.isEmpty())
			 flag=-1;
		else flag=0;
		return flag;
	}
}

class Producer implements Runnable {	//	生产者
	Store s;
	public Producer(Store s) {
		this.s = s;
	}
	public void run() {
		while(true){				
					s.add();		
			}
		}
		
	}
class Customer implements Runnable{		//	消费者
	Store s;
	public Customer(Store s) {
		this.s = s;
	}
	public void run() {
		while(true){
				s.get();			
		}		
	}
}

public class Producer_Customer {
	/**
	 * @param args
	 * @author zhangli
	 */
	public static void main(String[] args) {
		Store s = new Store();
		Producer p= new Producer(s);
		Customer c= new Customer(s);
		Producer p1= new Producer(s);
		Customer c1= new Customer(s);
		Producer p2= new Producer(s);
		Customer c2= new Customer(s);
		
		new Thread(p,"p0").start();
		new Thread(c,"c0").start();
		new Thread(p1,"p1").start();
		new Thread(c1,"c1").start();
		new Thread(p2,"p2").start();
		new Thread(c2,"c2").start();
	}

}


测试了一下,还不错,控制的还好吧;
测试结果如下:

p0 生产入仓库:[1--产品]
c2 消费了产品:[1--产品]
消费者 c2 :仓库无货,请稍后再来.....
消费者 c1 :仓库无货,请稍后再来.....
p2 生产入仓库:[2--产品]
p1 生产入仓库:[3--产品]
p1 生产入仓库:[4--产品]
c0 消费了产品:[2--产品]
p1 生产入仓库:[5--产品]
p1 生产入仓库:[6--产品]
p1 生产入仓库:[7--产品]
p2 生产入仓库:[8--产品]
p2 生产入仓库:[9--产品]
p2 生产入仓库:[10--产品]
p2 生产入仓库:[11--产品]
c2 消费了产品:[3--产品]
p0 生产入仓库:[12--产品]
p0 生产入仓库:[13--产品]
生产者 p0 :仓库已满,请稍后生产.....
c2 消费了产品:[4--产品]
p2 生产入仓库:[14--产品]
生产者 p1 :仓库已满,请稍后生产.....
c0 消费了产品:[5--产品]
c0 消费了产品:[6--产品]
c0 消费了产品:[7--产品]
1
3
分享到:
评论
5 楼 zl378837964 2012-09-09  
Shen.Yiyang 写道
你的两边的线程如果不工作的话,就是block(wait)吧,看不出什么制约的效果; 而且你拿数据和放数据,在一个对象上面wait/notify,实际上可能误唤醒吧;用blocking queue可能更好一点,它的实现是两个等待队列

我以前也写过。可能是我表达不准确吧,反正就是这个意思,另一篇你看看,是否有问题?交流一下也好。
4 楼 Shen.Yiyang 2012-09-06  
你的两边的线程如果不工作的话,就是block(wait)吧,看不出什么制约的效果; 而且你拿数据和放数据,在一个对象上面wait/notify,实际上可能误唤醒吧;用blocking queue可能更好一点,它的实现是两个等待队列
3 楼 Shen.Yiyang 2012-09-06  
zl378837964 写道
我没有用线程池,要的就是这效果,实现相互制约的线程控制啊!亲
目的不同不相语 ~ ~ ~

相互制约的线程控制是什么概念。。没听说过
2 楼 zl378837964 2012-09-06  
我没有用线程池,要的就是这效果,实现相互制约的线程控制啊!亲
目的不同不相语 ~ ~ ~
1 楼 Shen.Yiyang 2012-09-04  
生产消费模式在应对固定的吞吐量时,非常合适;但是在吞吐变化很大,线程时而空闲时而忙碌的场景下,我觉得转变思路,把生产消费的这种脚本模型 转化成 面向对象的task,用线程池是更合理,更具有维护性的做法。 一点想法,来自于前段时间有人问,怎么总结或者减少消费者之类的问题。

相关推荐

Global site tag (gtag.js) - Google Analytics